Skip to content

Commit a6ba5e2

Browse files
authored
Merge pull request #59 from district0x/vibemarket-integration
Vibemarket and toshi mart integration
2 parents 0901722 + 1038c4f commit a6ba5e2

35 files changed

Lines changed: 1403 additions & 274 deletions

bb.edn

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@
7474
(do
7575
(println "Starting Streamtide sidechain server")
7676
(shell (format "node sidechain_server/streamtide_sidechain_server.js %s" command-args))))}
77+
watch-dummy-coin-service
78+
{:doc "Watch and compile dummy coin service code CLJS -> JS in test/coin_service/**"
79+
:requires ([babashka.cli :as cli])
80+
:task (let [aliases (or *command-line-args* [])
81+
command-args (format "-M:dev:shadow-cljs%s watch dummy-coin-service"
82+
(clojure.string/join "" aliases))]
83+
(println "Starting watch dummy-coin-service args:" command-args)
84+
(clojure command-args))}
85+
run-dummy-coin-server {:doc "Start Node.js API server process"
86+
:task (do
87+
(println "Starting Coin Dummy API server")
88+
(shell "node test/coin_service/out/dummy_service.js"))}
7789
watch-server-tests {:doc "watch server tests"
7890
:task (do
7991
(println "Watch and compile server code changes tests")

contracts/streamtide.sol

Lines changed: 114 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
66
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
77
import "@openzeppelin/contracts/utils/Context.sol";
88
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9+
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
910

1011

11-
contract MVPCLR is OwnableUpgradeable {
12+
contract MVPCLR is OwnableUpgradeable, ReentrancyGuard {
1213

1314
event AdminAdded(address _admin);
1415
event AdminRemoved(address _admin);
@@ -33,6 +34,18 @@ contract MVPCLR is OwnableUpgradeable {
3334
uint256 roundId
3435
);
3536

37+
event DonateExternal(
38+
address sender,
39+
uint256 value,
40+
address patronAddress,
41+
uint256 roundId,
42+
uint16 externalType,
43+
address target,
44+
bytes callData,
45+
address token,
46+
uint256 gained
47+
);
48+
3649
event FailedDistribute(
3750
address receiver,
3851
uint256 amount
@@ -130,24 +143,114 @@ contract MVPCLR is OwnableUpgradeable {
130143
emit PatronsAdded(addresses);
131144
}
132145

133-
function donate(address[] memory patronAddresses, uint256[] memory amounts) public payable {
146+
function donate(
147+
address[] memory patronAddresses,
148+
uint256[] memory amounts,
149+
bytes[] calldata metadata,
150+
address[] calldata tokens
151+
) public payable nonReentrant {
134152
require(patronAddresses.length == amounts.length, "CLR:donate - Mismatch between number of patrons and amounts");
153+
require(patronAddresses.length == metadata.length, "CLR:donate - mismatch patrons/metadata");
154+
require(!isBlacklisted[_msgSender()], "Sender address is blacklisted");
155+
135156
uint256 totalAmount = 0;
136157
uint256 donationRoundId = roundIsClosed() ? 0 : roundId;
158+
137159
for (uint256 i = 0; i < patronAddresses.length; i++) {
138-
address patronAddress = patronAddresses[i];
139-
uint256 amount = amounts[i];
140-
totalAmount += amount;
141-
require(!isBlacklisted[_msgSender()], "Sender address is blacklisted");
142-
require(isPatron[patronAddress], "CLR:donate - Not a valid recipient");
143-
emit Donate(_msgSender(), amount, patronAddress, donationRoundId);
144-
bool success = payable(patronAddress).send(amount);
145-
require(success, "CLR:donate - Failed to send funds to recipient");
160+
totalAmount += _processDonation(
161+
patronAddresses[i],
162+
amounts[i],
163+
metadata[i],
164+
tokens[i],
165+
donationRoundId
166+
);
146167
}
147168

148-
require(totalAmount <= msg.value, "CLR:donate - Total amount donated is greater than the value sent");
169+
require(totalAmount <= msg.value, "CLR:donate - Total amount donated exceeds value sent");
149170
}
150171

172+
function _processDonation(
173+
address patronAddress,
174+
uint256 amount,
175+
bytes calldata data,
176+
address token,
177+
uint256 donationRoundId
178+
) internal returns (uint256) {
179+
require(!isBlacklisted[patronAddress], "Patron address is blacklisted");
180+
require(isPatron[patronAddress], "CLR:donate - Not a valid recipient");
181+
182+
if (data.length > 0) {
183+
_handleExternalDonation(patronAddress, amount, data, token, donationRoundId);
184+
} else {
185+
_handleDirectDonation(patronAddress, amount, donationRoundId);
186+
}
187+
188+
return amount;
189+
}
190+
191+
function _handleDirectDonation(
192+
address patronAddress,
193+
uint256 amount,
194+
uint256 donationRoundId
195+
) internal {
196+
bool success = payable(patronAddress).send(amount);
197+
require(success, "CLR:donate - Failed to send funds to recipient");
198+
199+
emit Donate(_msgSender(), amount, patronAddress, donationRoundId);
200+
}
201+
202+
function _handleExternalDonation(
203+
address patronAddress,
204+
uint256 amount,
205+
bytes calldata data,
206+
address token,
207+
uint256 donationRoundId
208+
) internal {
209+
(uint16 externalType, address target, bytes memory callData) = abi.decode(data, (uint16, address, bytes));
210+
require(target != address(0), "CLR:donate - invalid target");
211+
require(isContract(target), "CLR:donate - target must be contract");
212+
213+
uint256 gained = 0;
214+
uint256 beforeBal = 0;
215+
216+
if (token != address(0)) {
217+
beforeBal = IERC20(token).balanceOf(address(this));
218+
}
219+
{
220+
(bool success, bytes memory returndata) = payable(target).call{value: amount}(callData);
221+
require(success, _getRevertMsg(returndata));
222+
}
223+
if (token != address(0)) {
224+
gained = IERC20(token).balanceOf(address(this)) - beforeBal;
225+
if (gained > 0) {
226+
IERC20(token).transfer(_msgSender(), gained);
227+
}
228+
}
229+
230+
emit DonateExternal(
231+
_msgSender(),
232+
amount,
233+
patronAddress,
234+
donationRoundId,
235+
externalType,
236+
target,
237+
callData,
238+
token,
239+
gained
240+
);
241+
}
242+
243+
function isContract(address account) internal view returns (bool) {
244+
return account.code.length > 0;
245+
}
246+
247+
function _getRevertMsg(bytes memory returnData) private pure returns (string memory) {
248+
if (returnData.length < 68) return "CLR:donate - external call failed";
249+
assembly {
250+
returnData := add(returnData, 0x04)
251+
}
252+
return abi.decode(returnData, (string));
253+
}
151254

152255
function distribute(address payable[] memory patrons, uint[] memory amounts, address token) public onlyAdmin {
153256
require(patrons.length == amounts.length, "Length of patrons and amounts must be the same");

deps.edn

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@
1919
district0x/district-time {:mvn/version "1.0.1"}
2020
district0x/district-ui-component-form {:mvn/version "0.2.15"}
2121
district0x/district-ui-component-notification {:mvn/version "1.0.1"}
22+
district0x/district-ui-conversion-rates {:mvn/version "1.0.1"}
2223
district0x/district-ui-graphql {:mvn/version "1.0.15"}
2324
district0x/district-ui-logging {:mvn/version "1.1.0"}
2425
district0x/district-ui-notification {:mvn/version "1.0.1"}
2526
district0x/district-ui-window-size {:mvn/version "1.0.1"}
2627
is.d0x/cljs-web3-next {:mvn/version "24.2.10"}
2728
is.d0x/district-server-config {:mvn/version "24.2.10"}
2829
is.d0x/district-server-db {:mvn/version "24.6.19"}
29-
is.d0x/district-server-web3-events {:mvn/version "25.6.26"}
30+
is.d0x/district-server-web3-events {:mvn/version "25.10.30"}
3031
is.d0x/re-frame-web3-fx {:mvn/version "24.2.10"}
3132
is.d0x/district-sendgrid {:mvn/version "24.2.10"}
3233
is.d0x/district-ui-reagent-render {:mvn/version "24.2.10"}

migrations/_99_update_streamtide.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = async(deployer, network, accounts) => {
2525
}
2626

2727
await status.step(async () => {
28-
const streamtide = await deployer.deploy(Streamtide, Object.assign(opts, {gas: 2000000}));
28+
const streamtide = await deployer.deploy(Streamtide, Object.assign(opts, {gas: 3000000}));
2929
return {[sk.streamtideAddr]: streamtide.address};
3030
});
3131

resources/scss/layouts/profile.scss

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,51 @@
133133
}
134134
}
135135
.btsProfile {
136-
width: 100%;
137-
max-width: 412px;
138-
margin: 0 auto 28.22px;
136+
width: fit-content;
137+
margin: 0 auto 28px;
138+
display: flex;
139+
flex-direction: column;
140+
align-items: center;
139141
.btBasic {
140-
width: 100%;
141-
margin-bottom: 13.38px;
142-
font-size: 18px;
143-
letter-spacing: 1.87px;
144-
&:last-child {
145-
margin-bottom: 0;
146-
}
142+
line-height: 24px;
143+
display: inline-block;
144+
white-space: normal;
145+
text-align: center;
146+
max-width: 100%;
147+
height: unset;
148+
padding: 14px 50px;
149+
min-width: 280px;
150+
margin-bottom: 13.38px;
151+
font-size: 16px;
152+
&:last-child {
153+
margin-bottom: 0;
154+
}
147155
}
156+
.coin-link {
157+
margin-bottom: 12px;
158+
height: 100%;
159+
display: block;
160+
.coin-logo {
161+
height: 200px;
162+
}
163+
.coin-custom-logo {
164+
width: 138px;
165+
height: 200px;
166+
display: flex;
167+
justify-content: center;
168+
align-items: center;
169+
font-family: Arial, sans-serif;
170+
font-size: 26px;
171+
font-weight: bold;
172+
color: white;
173+
background: linear-gradient(135deg, #ff1edc, #0064ff);
174+
border-radius: 20px;
175+
text-transform: uppercase;
176+
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
177+
}
178+
179+
180+
}
148181
}
149182
.medias {
150183
.media {
@@ -309,7 +342,13 @@
309342
margin-bottom: 34px;
310343
.btBasic {
311344
margin-bottom: 24px;
345+
font-size: 18px;
346+
letter-spacing: 1.87px;
347+
min-width: 350px;
312348
}
349+
.coin-link {
350+
margin-bottom: 20px;
351+
}
313352
}
314353
}
315354
}

resources/scss/layouts/profileEdit.scss

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
}
100100
}
101101
}
102-
.generalInfo, .min-donation, .perks {
102+
.generalInfo, .donation-config, .perks {
103103
margin-bottom: 23px;
104104
label.inputField {
105105
display: flex;
@@ -520,9 +520,21 @@
520520
min-width: 189px;
521521
}
522522
}
523-
.min-donation {
523+
.donations-configs {
524524
margin-top: 3em;
525-
}
525+
a {
526+
color: goldenrod;
527+
}
528+
}
529+
.donations-config {
530+
margin-top: 15px;
531+
margin-left: 1em;
532+
}
533+
.donation-config {
534+
span {
535+
min-width: fit-content;
536+
}
537+
}
526538
}
527539
.submitField {
528540
background: $bgSite;

0 commit comments

Comments
 (0)