Skip to content

Commit 6338780

Browse files
feat: add direct donation button (#3560)
* wip * feat: add directAllocation to allo-v2 * fix: build issue * feat: update allo sdk version * feat: fetch txData from sdk * fix: build issues * fix: other issues * feat: update ui * feat: add useDirectAllocation hook * feat: add progress modal cmponent in explorer * feat: add getDirectAllocationPoolId * feat: add handleDonate to project * update UI * fix: zeroAddress bug * feat: minor ui updates * test: update tests * update poolId (new contract deployed * swap out fo sdk * chore: code cleanup * feat: handle case when wallet is not connected * feat: update max height * feat: handle error states * feat: show donate button only on chains that support direct donation * feat: add error modal * tests: fix failing tests * fix: erc20 donation issue * fix: decimal issue on donation modal * chore: refactor code * chore: update lock file * feat: refactor getbalance in project page --------- Co-authored-by: Aditya Anand M C <aditya.anandmc@gmail.com>
1 parent 011941a commit 6338780

File tree

13 files changed

+1124
-92
lines changed

13 files changed

+1124
-92
lines changed

packages/common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"test:watch": "vitest watch"
1717
},
1818
"dependencies": {
19-
"@allo-team/allo-v2-sdk": "^1.0.76",
19+
"@allo-team/allo-v2-sdk": "^1.0.77",
2020
"@ethersproject/abstract-signer": "^5.7.0",
2121
"@ethersproject/providers": "^5.7.2",
2222
"@gitcoin/gitcoin-chain-data": "^1.0.17",

packages/common/src/allo/allo.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,23 @@ export interface Allo {
244244
indexingStatus: Result<null>;
245245
}
246246
>;
247+
248+
directAllocation: (args: {
249+
tokenAddress: Address;
250+
poolId: string;
251+
amount: bigint;
252+
recipient: Address;
253+
nonce: bigint;
254+
requireTokenApproval?: boolean;
255+
}) => AlloOperation<
256+
Result<null>,
257+
{
258+
tokenApprovalStatus: Result<TransactionReceipt | null>;
259+
transaction: Result<Hex>;
260+
transactionStatus: Result<TransactionReceipt>;
261+
indexingStatus: Result<null>;
262+
}
263+
>;
247264
}
248265

249266
export { AlloOperation };

packages/common/src/allo/backends/allo-v1.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,28 @@ export class AlloV1 implements Allo {
13101310
return error(result);
13111311
});
13121312
}
1313+
1314+
directAllocation(args: {
1315+
tokenAddress: Address;
1316+
poolId: string;
1317+
amount: bigint;
1318+
recipient: Address;
1319+
nonce: bigint;
1320+
requireTokenApproval?: boolean;
1321+
}): AlloOperation<
1322+
Result<null>,
1323+
{
1324+
tokenApprovalStatus: Result<TransactionReceipt | null>;
1325+
transaction: Result<Hex>;
1326+
transactionStatus: Result<TransactionReceipt>;
1327+
indexingStatus: Result<null>;
1328+
}
1329+
> {
1330+
return new AlloOperation(async () => {
1331+
const result = new AlloError(`Unsupported on v1 ${args}`);
1332+
return error(result);
1333+
});
1334+
}
13131335
}
13141336
// todo: move this out?
13151337
export type CreateRoundArgs = {

packages/common/src/allo/backends/allo-v2.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
AlloAbi,
33
Allo as AlloV2Contract,
44
CreateProfileArgs,
5+
DirectAllocationStrategy,
56
DirectGrantsLiteStrategy,
67
DirectGrantsLiteStrategyTypes,
78
DonationVotingMerkleDistributionDirectTransferStrategyAbi,
@@ -82,6 +83,24 @@ export function getAlloAddress(chainId: number) {
8283
return allo.address();
8384
}
8485

86+
export function getDirectAllocationPoolId(chainId: number) {
87+
switch (chainId) {
88+
case 11155111:
89+
return 386;
90+
default:
91+
return undefined;
92+
}
93+
}
94+
95+
export function getDirectAllocationStrategyAddress(chainId: number) {
96+
switch (chainId) {
97+
case 11155111:
98+
return "0xd60BCfa8714949c478d88da51A7450703A32Cf35";
99+
default:
100+
return undefined;
101+
}
102+
}
103+
85104
export class AlloV2 implements Allo {
86105
private transactionSender: TransactionSender;
87106
private ipfsUploader: IpfsUploader;
@@ -1435,6 +1454,114 @@ export class AlloV2 implements Allo {
14351454
return success(null);
14361455
});
14371456
}
1457+
1458+
directAllocation(args: {
1459+
tokenAddress: Address;
1460+
poolId: string;
1461+
amount: bigint;
1462+
recipient: Address;
1463+
nonce: bigint;
1464+
requireTokenApproval?: boolean;
1465+
}): AlloOperation<
1466+
Result<null>,
1467+
{
1468+
tokenApprovalStatus: Result<TransactionReceipt | null>;
1469+
transaction: Result<Hex>;
1470+
transactionStatus: Result<TransactionReceipt>;
1471+
indexingStatus: Result<null>;
1472+
}
1473+
> {
1474+
return new AlloOperation(async ({ emit }) => {
1475+
if (isNaN(Number(args.poolId))) {
1476+
return error(new AlloError("Pool ID is not a valid Allo V2 pool ID"));
1477+
}
1478+
1479+
const poolId = BigInt(args.poolId);
1480+
1481+
const strategy = new DirectAllocationStrategy({
1482+
chain: this.chainId,
1483+
poolId: poolId,
1484+
});
1485+
1486+
const strategyAddress = getDirectAllocationStrategyAddress(this.chainId);
1487+
1488+
if (strategyAddress === undefined) {
1489+
return error(new AlloError("Direct allocation strategy not found"));
1490+
}
1491+
1492+
if (args.tokenAddress === zeroAddress || !args.requireTokenApproval) {
1493+
emit("tokenApprovalStatus", success(null));
1494+
} else {
1495+
const approvalTx = await sendTransaction(this.transactionSender, {
1496+
address: args.tokenAddress,
1497+
abi: Erc20ABI,
1498+
functionName: "approve",
1499+
args: [strategyAddress, args.amount],
1500+
});
1501+
1502+
if (approvalTx.type === "error") {
1503+
const result = new AlloError(
1504+
"Failed to approve token transfer",
1505+
approvalTx.error
1506+
);
1507+
emit("tokenApprovalStatus", error(result));
1508+
return error(result);
1509+
}
1510+
try {
1511+
const receipt = await this.transactionSender.wait(approvalTx.value);
1512+
emit("tokenApprovalStatus", success(receipt));
1513+
} catch (err) {
1514+
const result = new AlloError("Failed to approve token transfer", err);
1515+
emit("tokenApprovalStatus", error(result));
1516+
return error(result);
1517+
}
1518+
}
1519+
1520+
let _token = args.tokenAddress;
1521+
if (_token === zeroAddress) {
1522+
_token = getAddress(NATIVE);
1523+
}
1524+
1525+
const txData = strategy.getAllocateData({
1526+
profileOwner: args.recipient,
1527+
amount: BigInt(args.amount.toString()),
1528+
token: _token,
1529+
nonce: args.nonce,
1530+
});
1531+
1532+
const tx = await sendRawTransaction(this.transactionSender, {
1533+
to: txData.to,
1534+
data: txData.data,
1535+
value: BigInt(txData.value),
1536+
});
1537+
1538+
emit("transaction", tx);
1539+
1540+
if (tx.type === "error") {
1541+
return tx;
1542+
}
1543+
1544+
let receipt: TransactionReceipt;
1545+
1546+
try {
1547+
receipt = await this.transactionSender.wait(tx.value);
1548+
emit("transactionStatus", success(receipt));
1549+
} catch (err) {
1550+
const result = new AlloError("Failed to fund round", err);
1551+
emit("transactionStatus", error(result));
1552+
return error(result);
1553+
}
1554+
1555+
await this.waitUntilIndexerSynced({
1556+
chainId: this.chainId,
1557+
blockNumber: receipt.blockNumber,
1558+
});
1559+
1560+
emit("indexingStatus", success(null));
1561+
1562+
return success(null);
1563+
});
1564+
}
14381565
}
14391566

14401567
export function serializeProject(project: ProjectWithMerkleProof) {

packages/common/src/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,10 @@ export type InputType =
9494
export type DeepRequired<T> = {
9595
[K in keyof T]: Required<DeepRequired<T[K]>>;
9696
};
97+
98+
export type Allocation = {
99+
profileOwner: `0x${string}`;
100+
amount: bigint;
101+
token: `0x${string}`;
102+
nonce: bigint;
103+
};

packages/grant-explorer/src/features/common/GenericModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface InfoModalProps {
1111
}
1212

1313
export default function InfoModal({
14-
title = "Information Title",
14+
title = "",
1515
titleSize = "sm",
1616
isOpen = false,
1717
setIsOpen = () => {

0 commit comments

Comments
 (0)