thirdweb 5.88.2-nightly-0c1bb6ccaec9dc4edf596dac7f7623d0ad90f757-20250212000327 → 5.88.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/exports/extensions/erc1155.js +4 -2
- package/dist/cjs/exports/extensions/erc1155.js.map +1 -1
- package/dist/cjs/exports/extensions/erc20.js +3 -1
- package/dist/cjs/exports/extensions/erc20.js.map +1 -1
- package/dist/cjs/exports/extensions/erc721.js +4 -2
- package/dist/cjs/exports/extensions/erc721.js.map +1 -1
- package/dist/cjs/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.js +191 -0
- package/dist/cjs/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.js.map +1 -0
- package/dist/cjs/extensions/erc1155/drops/read/canClaim.js +45 -0
- package/dist/cjs/extensions/erc1155/drops/read/canClaim.js.map +1 -0
- package/dist/cjs/extensions/erc20/__generated__/DropERC20/read/verifyClaim.js +182 -0
- package/dist/cjs/extensions/erc20/__generated__/DropERC20/read/verifyClaim.js.map +1 -0
- package/dist/cjs/extensions/erc20/drops/read/canClaim.js +51 -0
- package/dist/cjs/extensions/erc20/drops/read/canClaim.js.map +1 -0
- package/dist/cjs/extensions/erc721/__generated__/DropERC721/read/verifyClaim.js +182 -0
- package/dist/cjs/extensions/erc721/__generated__/DropERC721/read/verifyClaim.js.map +1 -0
- package/dist/cjs/extensions/erc721/drops/read/canClaim.js +42 -0
- package/dist/cjs/extensions/erc721/drops/read/canClaim.js.map +1 -0
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +12 -5
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js +6 -5
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.js +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js +7 -3
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js.map +1 -1
- package/dist/cjs/react/web/utils/errors.js +6 -1
- package/dist/cjs/react/web/utils/errors.js.map +1 -1
- package/dist/cjs/transaction/extract-error.js +11 -4
- package/dist/cjs/transaction/extract-error.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/esm/exports/extensions/erc1155.js +1 -0
- package/dist/esm/exports/extensions/erc1155.js.map +1 -1
- package/dist/esm/exports/extensions/erc20.js +1 -0
- package/dist/esm/exports/extensions/erc20.js.map +1 -1
- package/dist/esm/exports/extensions/erc721.js +1 -0
- package/dist/esm/exports/extensions/erc721.js.map +1 -1
- package/dist/esm/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.js +183 -0
- package/dist/esm/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.js.map +1 -0
- package/dist/esm/extensions/erc1155/drops/read/canClaim.js +42 -0
- package/dist/esm/extensions/erc1155/drops/read/canClaim.js.map +1 -0
- package/dist/esm/extensions/erc20/__generated__/DropERC20/read/verifyClaim.js +174 -0
- package/dist/esm/extensions/erc20/__generated__/DropERC20/read/verifyClaim.js.map +1 -0
- package/dist/esm/extensions/erc20/drops/read/canClaim.js +48 -0
- package/dist/esm/extensions/erc20/drops/read/canClaim.js.map +1 -0
- package/dist/esm/extensions/erc721/__generated__/DropERC721/read/verifyClaim.js +174 -0
- package/dist/esm/extensions/erc721/__generated__/DropERC721/read/verifyClaim.js.map +1 -0
- package/dist/esm/extensions/erc721/drops/read/canClaim.js +39 -0
- package/dist/esm/extensions/erc721/drops/read/canClaim.js.map +1 -0
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +12 -5
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js +6 -5
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.js +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js +7 -3
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js.map +1 -1
- package/dist/esm/react/web/utils/errors.js +6 -1
- package/dist/esm/react/web/utils/errors.js.map +1 -1
- package/dist/esm/transaction/extract-error.js +11 -5
- package/dist/esm/transaction/extract-error.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/exports/extensions/erc1155.d.ts +1 -0
- package/dist/types/exports/extensions/erc1155.d.ts.map +1 -1
- package/dist/types/exports/extensions/erc20.d.ts +1 -0
- package/dist/types/exports/extensions/erc20.d.ts.map +1 -1
- package/dist/types/exports/extensions/erc721.d.ts +1 -0
- package/dist/types/exports/extensions/erc721.d.ts.map +1 -1
- package/dist/types/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.d.ts +143 -0
- package/dist/types/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.d.ts.map +1 -0
- package/dist/types/extensions/erc1155/drops/read/canClaim.d.ts +13 -0
- package/dist/types/extensions/erc1155/drops/read/canClaim.d.ts.map +1 -0
- package/dist/types/extensions/erc20/__generated__/DropERC20/read/verifyClaim.d.ts +136 -0
- package/dist/types/extensions/erc20/__generated__/DropERC20/read/verifyClaim.d.ts.map +1 -0
- package/dist/types/extensions/erc20/drops/read/canClaim.d.ts +15 -0
- package/dist/types/extensions/erc20/drops/read/canClaim.d.ts.map +1 -0
- package/dist/types/extensions/erc721/__generated__/DropERC721/read/verifyClaim.d.ts +136 -0
- package/dist/types/extensions/erc721/__generated__/DropERC721/read/verifyClaim.d.ts.map +1 -0
- package/dist/types/extensions/erc721/drops/read/canClaim.d.ts +12 -0
- package/dist/types/extensions/erc721/drops/read/canClaim.d.ts.map +1 -0
- package/dist/types/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.d.ts.map +1 -1
- package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.d.ts.map +1 -1
- package/dist/types/react/web/utils/errors.d.ts.map +1 -1
- package/dist/types/transaction/extract-error.d.ts +4 -0
- package/dist/types/transaction/extract-error.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/exports/extensions/erc1155.ts +5 -0
- package/src/exports/extensions/erc20.ts +5 -0
- package/src/exports/extensions/erc721.ts +5 -0
- package/src/extensions/erc1155/__generated__/DropERC1155/read/verifyClaim.ts +223 -0
- package/src/extensions/erc1155/drop1155.test.ts +42 -0
- package/src/extensions/erc1155/drops/read/canClaim.ts +57 -0
- package/src/extensions/erc20/__generated__/DropERC20/read/verifyClaim.ts +213 -0
- package/src/extensions/erc20/drop20.test.ts +38 -0
- package/src/extensions/erc20/drops/read/canClaim.ts +65 -0
- package/src/extensions/erc721/__generated__/DropERC721/read/verifyClaim.ts +213 -0
- package/src/extensions/erc721/drop721.test.ts +39 -0
- package/src/extensions/erc721/drops/read/canClaim.ts +53 -0
- package/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +16 -3
- package/src/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.tsx +27 -20
- package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.tsx +1 -2
- package/src/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.tsx +28 -16
- package/src/react/web/utils/errors.ts +6 -1
- package/src/transaction/actions/gasless/providers/engine.test.ts +1 -1
- package/src/transaction/actions/gasless/providers/openzeppelin.test.ts +1 -1
- package/src/transaction/extract-error.ts +15 -13
- package/src/version.ts +1 -1
@@ -14,6 +14,7 @@ import { resolvePromisedValue } from "../../utils/promise/resolve-promised-value
|
|
14
14
|
import { toEther } from "../../utils/units.js";
|
15
15
|
import { name } from "../common/read/name.js";
|
16
16
|
import { deployERC20Contract } from "../prebuilts/deploy-erc20.js";
|
17
|
+
import { canClaim } from "./drops/read/canClaim.js";
|
17
18
|
import { getClaimConditions } from "./drops/read/getClaimConditions.js";
|
18
19
|
import { claimTo } from "./drops/write/claimTo.js";
|
19
20
|
import { resetClaimEligibility } from "./drops/write/resetClaimEligibility.js";
|
@@ -76,6 +77,18 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
76
77
|
}),
|
77
78
|
account: TEST_ACCOUNT_A,
|
78
79
|
});
|
80
|
+
|
81
|
+
expect(
|
82
|
+
await canClaim({
|
83
|
+
contract,
|
84
|
+
claimer: TEST_ACCOUNT_A.address,
|
85
|
+
quantity: "1",
|
86
|
+
}),
|
87
|
+
).toMatchInlineSnapshot(`
|
88
|
+
{
|
89
|
+
"result": true,
|
90
|
+
}
|
91
|
+
`);
|
79
92
|
const claimTx = claimTo({
|
80
93
|
contract,
|
81
94
|
to: TEST_ACCOUNT_A.address,
|
@@ -180,6 +193,31 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
180
193
|
}
|
181
194
|
`);
|
182
195
|
|
196
|
+
expect(
|
197
|
+
await canClaim({
|
198
|
+
contract,
|
199
|
+
claimer: TEST_ACCOUNT_A.address,
|
200
|
+
quantity: "1",
|
201
|
+
}),
|
202
|
+
).toMatchInlineSnapshot(`
|
203
|
+
{
|
204
|
+
"result": true,
|
205
|
+
}
|
206
|
+
`);
|
207
|
+
|
208
|
+
expect(
|
209
|
+
await canClaim({
|
210
|
+
contract,
|
211
|
+
claimer: TEST_ACCOUNT_B.address,
|
212
|
+
quantity: "1",
|
213
|
+
}),
|
214
|
+
).toMatchInlineSnapshot(`
|
215
|
+
{
|
216
|
+
"reason": "DropClaimExceedLimit - 0,1000000000000000000",
|
217
|
+
"result": false,
|
218
|
+
}
|
219
|
+
`);
|
220
|
+
|
183
221
|
await sendAndConfirmTransaction({
|
184
222
|
account: TEST_ACCOUNT_A,
|
185
223
|
transaction: claimTo({
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { extractErrorResult } from "../../../../transaction/extract-error.js";
|
2
|
+
import type { BaseTransactionOptions } from "../../../../transaction/types.js";
|
3
|
+
import { getClaimParams } from "../../../../utils/extensions/drops/get-claim-params.js";
|
4
|
+
import { verifyClaim } from "../../__generated__/DropERC20/read/verifyClaim.js";
|
5
|
+
import { getActiveClaimConditionId } from "../../__generated__/IDropERC20/read/getActiveClaimConditionId.js";
|
6
|
+
import { decimals } from "../../read/decimals.js";
|
7
|
+
|
8
|
+
export type CanClaimParams = {
|
9
|
+
claimer: string;
|
10
|
+
from?: string;
|
11
|
+
} & ({ quantityInWei: bigint } | { quantity: string });
|
12
|
+
|
13
|
+
export type CanClaimResult = {
|
14
|
+
result: boolean;
|
15
|
+
reason?: string;
|
16
|
+
};
|
17
|
+
|
18
|
+
export async function canClaim(
|
19
|
+
options: BaseTransactionOptions<CanClaimParams>,
|
20
|
+
): Promise<CanClaimResult> {
|
21
|
+
const quantityWei = await (async () => {
|
22
|
+
if ("quantityInWei" in options) {
|
23
|
+
return options.quantityInWei;
|
24
|
+
}
|
25
|
+
|
26
|
+
const { toUnits } = await import("../../../../utils/units.js");
|
27
|
+
return toUnits(
|
28
|
+
options.quantity,
|
29
|
+
await decimals({ contract: options.contract }),
|
30
|
+
);
|
31
|
+
})();
|
32
|
+
const [conditionId, { quantity, currency, pricePerToken, allowlistProof }] =
|
33
|
+
await Promise.all([
|
34
|
+
getActiveClaimConditionId({
|
35
|
+
contract: options.contract,
|
36
|
+
}),
|
37
|
+
getClaimParams({
|
38
|
+
contract: options.contract,
|
39
|
+
quantity: quantityWei,
|
40
|
+
to: options.claimer,
|
41
|
+
type: "erc20",
|
42
|
+
from: options.from,
|
43
|
+
tokenDecimals: await decimals({ contract: options.contract }),
|
44
|
+
}),
|
45
|
+
]);
|
46
|
+
try {
|
47
|
+
await verifyClaim({
|
48
|
+
contract: options.contract,
|
49
|
+
claimer: options.claimer,
|
50
|
+
quantity,
|
51
|
+
currency,
|
52
|
+
pricePerToken,
|
53
|
+
allowlistProof,
|
54
|
+
conditionId,
|
55
|
+
});
|
56
|
+
return {
|
57
|
+
result: true,
|
58
|
+
};
|
59
|
+
} catch (error) {
|
60
|
+
return {
|
61
|
+
result: false,
|
62
|
+
reason: await extractErrorResult({ error, contract: options.contract }),
|
63
|
+
};
|
64
|
+
}
|
65
|
+
}
|
@@ -0,0 +1,213 @@
|
|
1
|
+
import type { AbiParameterToPrimitiveType } from "abitype";
|
2
|
+
import { readContract } from "../../../../../transaction/read-contract.js";
|
3
|
+
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
|
4
|
+
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
|
5
|
+
import { decodeAbiParameters } from "viem";
|
6
|
+
import type { Hex } from "../../../../../utils/encoding/hex.js";
|
7
|
+
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Represents the parameters for the "verifyClaim" function.
|
11
|
+
*/
|
12
|
+
export type VerifyClaimParams = {
|
13
|
+
conditionId: AbiParameterToPrimitiveType<{
|
14
|
+
type: "uint256";
|
15
|
+
name: "_conditionId";
|
16
|
+
}>;
|
17
|
+
claimer: AbiParameterToPrimitiveType<{ type: "address"; name: "_claimer" }>;
|
18
|
+
quantity: AbiParameterToPrimitiveType<{ type: "uint256"; name: "_quantity" }>;
|
19
|
+
currency: AbiParameterToPrimitiveType<{ type: "address"; name: "_currency" }>;
|
20
|
+
pricePerToken: AbiParameterToPrimitiveType<{
|
21
|
+
type: "uint256";
|
22
|
+
name: "_pricePerToken";
|
23
|
+
}>;
|
24
|
+
allowlistProof: AbiParameterToPrimitiveType<{
|
25
|
+
type: "tuple";
|
26
|
+
name: "_allowlistProof";
|
27
|
+
components: [
|
28
|
+
{ type: "bytes32[]"; name: "proof" },
|
29
|
+
{ type: "uint256"; name: "quantityLimitPerWallet" },
|
30
|
+
{ type: "uint256"; name: "pricePerToken" },
|
31
|
+
{ type: "address"; name: "currency" },
|
32
|
+
];
|
33
|
+
}>;
|
34
|
+
};
|
35
|
+
|
36
|
+
export const FN_SELECTOR = "0x23a2902b" as const;
|
37
|
+
const FN_INPUTS = [
|
38
|
+
{
|
39
|
+
type: "uint256",
|
40
|
+
name: "_conditionId",
|
41
|
+
},
|
42
|
+
{
|
43
|
+
type: "address",
|
44
|
+
name: "_claimer",
|
45
|
+
},
|
46
|
+
{
|
47
|
+
type: "uint256",
|
48
|
+
name: "_quantity",
|
49
|
+
},
|
50
|
+
{
|
51
|
+
type: "address",
|
52
|
+
name: "_currency",
|
53
|
+
},
|
54
|
+
{
|
55
|
+
type: "uint256",
|
56
|
+
name: "_pricePerToken",
|
57
|
+
},
|
58
|
+
{
|
59
|
+
type: "tuple",
|
60
|
+
name: "_allowlistProof",
|
61
|
+
components: [
|
62
|
+
{
|
63
|
+
type: "bytes32[]",
|
64
|
+
name: "proof",
|
65
|
+
},
|
66
|
+
{
|
67
|
+
type: "uint256",
|
68
|
+
name: "quantityLimitPerWallet",
|
69
|
+
},
|
70
|
+
{
|
71
|
+
type: "uint256",
|
72
|
+
name: "pricePerToken",
|
73
|
+
},
|
74
|
+
{
|
75
|
+
type: "address",
|
76
|
+
name: "currency",
|
77
|
+
},
|
78
|
+
],
|
79
|
+
},
|
80
|
+
] as const;
|
81
|
+
const FN_OUTPUTS = [
|
82
|
+
{
|
83
|
+
type: "bool",
|
84
|
+
name: "isOverride",
|
85
|
+
},
|
86
|
+
] as const;
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Checks if the `verifyClaim` method is supported by the given contract.
|
90
|
+
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
|
91
|
+
* @returns A boolean indicating if the `verifyClaim` method is supported.
|
92
|
+
* @extension ERC721
|
93
|
+
* @example
|
94
|
+
* ```ts
|
95
|
+
* import { isVerifyClaimSupported } from "thirdweb/extensions/erc721";
|
96
|
+
* const supported = isVerifyClaimSupported(["0x..."]);
|
97
|
+
* ```
|
98
|
+
*/
|
99
|
+
export function isVerifyClaimSupported(availableSelectors: string[]) {
|
100
|
+
return detectMethod({
|
101
|
+
availableSelectors,
|
102
|
+
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
|
103
|
+
});
|
104
|
+
}
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Encodes the parameters for the "verifyClaim" function.
|
108
|
+
* @param options - The options for the verifyClaim function.
|
109
|
+
* @returns The encoded ABI parameters.
|
110
|
+
* @extension ERC721
|
111
|
+
* @example
|
112
|
+
* ```ts
|
113
|
+
* import { encodeVerifyClaimParams } from "thirdweb/extensions/erc721";
|
114
|
+
* const result = encodeVerifyClaimParams({
|
115
|
+
* conditionId: ...,
|
116
|
+
* claimer: ...,
|
117
|
+
* quantity: ...,
|
118
|
+
* currency: ...,
|
119
|
+
* pricePerToken: ...,
|
120
|
+
* allowlistProof: ...,
|
121
|
+
* });
|
122
|
+
* ```
|
123
|
+
*/
|
124
|
+
export function encodeVerifyClaimParams(options: VerifyClaimParams) {
|
125
|
+
return encodeAbiParameters(FN_INPUTS, [
|
126
|
+
options.conditionId,
|
127
|
+
options.claimer,
|
128
|
+
options.quantity,
|
129
|
+
options.currency,
|
130
|
+
options.pricePerToken,
|
131
|
+
options.allowlistProof,
|
132
|
+
]);
|
133
|
+
}
|
134
|
+
|
135
|
+
/**
|
136
|
+
* Encodes the "verifyClaim" function into a Hex string with its parameters.
|
137
|
+
* @param options - The options for the verifyClaim function.
|
138
|
+
* @returns The encoded hexadecimal string.
|
139
|
+
* @extension ERC721
|
140
|
+
* @example
|
141
|
+
* ```ts
|
142
|
+
* import { encodeVerifyClaim } from "thirdweb/extensions/erc721";
|
143
|
+
* const result = encodeVerifyClaim({
|
144
|
+
* conditionId: ...,
|
145
|
+
* claimer: ...,
|
146
|
+
* quantity: ...,
|
147
|
+
* currency: ...,
|
148
|
+
* pricePerToken: ...,
|
149
|
+
* allowlistProof: ...,
|
150
|
+
* });
|
151
|
+
* ```
|
152
|
+
*/
|
153
|
+
export function encodeVerifyClaim(options: VerifyClaimParams) {
|
154
|
+
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
|
155
|
+
// we can do this because we know the specific formats of the values
|
156
|
+
return (FN_SELECTOR +
|
157
|
+
encodeVerifyClaimParams(options).slice(
|
158
|
+
2,
|
159
|
+
)) as `${typeof FN_SELECTOR}${string}`;
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* Decodes the result of the verifyClaim function call.
|
164
|
+
* @param result - The hexadecimal result to decode.
|
165
|
+
* @returns The decoded result as per the FN_OUTPUTS definition.
|
166
|
+
* @extension ERC721
|
167
|
+
* @example
|
168
|
+
* ```ts
|
169
|
+
* import { decodeVerifyClaimResult } from "thirdweb/extensions/erc721";
|
170
|
+
* const result = decodeVerifyClaimResultResult("...");
|
171
|
+
* ```
|
172
|
+
*/
|
173
|
+
export function decodeVerifyClaimResult(result: Hex) {
|
174
|
+
return decodeAbiParameters(FN_OUTPUTS, result)[0];
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
* Calls the "verifyClaim" function on the contract.
|
179
|
+
* @param options - The options for the verifyClaim function.
|
180
|
+
* @returns The parsed result of the function call.
|
181
|
+
* @extension ERC721
|
182
|
+
* @example
|
183
|
+
* ```ts
|
184
|
+
* import { verifyClaim } from "thirdweb/extensions/erc721";
|
185
|
+
*
|
186
|
+
* const result = await verifyClaim({
|
187
|
+
* contract,
|
188
|
+
* conditionId: ...,
|
189
|
+
* claimer: ...,
|
190
|
+
* quantity: ...,
|
191
|
+
* currency: ...,
|
192
|
+
* pricePerToken: ...,
|
193
|
+
* allowlistProof: ...,
|
194
|
+
* });
|
195
|
+
*
|
196
|
+
* ```
|
197
|
+
*/
|
198
|
+
export async function verifyClaim(
|
199
|
+
options: BaseTransactionOptions<VerifyClaimParams>,
|
200
|
+
) {
|
201
|
+
return readContract({
|
202
|
+
contract: options.contract,
|
203
|
+
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
|
204
|
+
params: [
|
205
|
+
options.conditionId,
|
206
|
+
options.claimer,
|
207
|
+
options.quantity,
|
208
|
+
options.currency,
|
209
|
+
options.pricePerToken,
|
210
|
+
options.allowlistProof,
|
211
|
+
],
|
212
|
+
});
|
213
|
+
}
|
@@ -25,6 +25,7 @@ import { setClaimConditions } from "./drops/write/setClaimConditions.js";
|
|
25
25
|
import { getNFT } from "./read/getNFT.js";
|
26
26
|
import { lazyMint } from "./write/lazyMint.js";
|
27
27
|
|
28
|
+
import { canClaim } from "./drops/read/canClaim.js";
|
28
29
|
describe.runIf(process.env.TW_SECRET_KEY)(
|
29
30
|
"DropERC721",
|
30
31
|
{
|
@@ -121,6 +122,19 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
121
122
|
}),
|
122
123
|
account: TEST_ACCOUNT_A,
|
123
124
|
});
|
125
|
+
|
126
|
+
expect(
|
127
|
+
await canClaim({
|
128
|
+
contract,
|
129
|
+
claimer: TEST_ACCOUNT_A.address,
|
130
|
+
quantity: 1n,
|
131
|
+
}),
|
132
|
+
).toMatchInlineSnapshot(`
|
133
|
+
{
|
134
|
+
"result": true,
|
135
|
+
}
|
136
|
+
`);
|
137
|
+
|
124
138
|
const claimTx = claimTo({
|
125
139
|
contract,
|
126
140
|
to: TEST_ACCOUNT_A.address,
|
@@ -208,6 +222,31 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
208
222
|
balanceOf({ contract, owner: TEST_ACCOUNT_B.address }),
|
209
223
|
).resolves.toBe(0n);
|
210
224
|
|
225
|
+
expect(
|
226
|
+
await canClaim({
|
227
|
+
contract,
|
228
|
+
claimer: TEST_ACCOUNT_A.address,
|
229
|
+
quantity: 1n,
|
230
|
+
}),
|
231
|
+
).toMatchInlineSnapshot(`
|
232
|
+
{
|
233
|
+
"result": true,
|
234
|
+
}
|
235
|
+
`);
|
236
|
+
|
237
|
+
expect(
|
238
|
+
await canClaim({
|
239
|
+
contract,
|
240
|
+
claimer: TEST_ACCOUNT_B.address,
|
241
|
+
quantity: 1n,
|
242
|
+
}),
|
243
|
+
).toMatchInlineSnapshot(`
|
244
|
+
{
|
245
|
+
"reason": "DropClaimExceedLimit - 0,1",
|
246
|
+
"result": false,
|
247
|
+
}
|
248
|
+
`);
|
249
|
+
|
211
250
|
await sendAndConfirmTransaction({
|
212
251
|
account: TEST_ACCOUNT_A,
|
213
252
|
transaction: claimTo({
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import { extractErrorResult } from "../../../../transaction/extract-error.js";
|
2
|
+
import type { BaseTransactionOptions } from "../../../../transaction/types.js";
|
3
|
+
import { getClaimParams } from "../../../../utils/extensions/drops/get-claim-params.js";
|
4
|
+
import { verifyClaim } from "../../__generated__/DropERC721/read/verifyClaim.js";
|
5
|
+
import { getActiveClaimConditionId } from "../../__generated__/IDrop/read/getActiveClaimConditionId.js";
|
6
|
+
|
7
|
+
export type CanClaimParams = {
|
8
|
+
claimer: string;
|
9
|
+
quantity: bigint;
|
10
|
+
from?: string;
|
11
|
+
};
|
12
|
+
|
13
|
+
export type CanClaimResult = {
|
14
|
+
result: boolean;
|
15
|
+
reason?: string;
|
16
|
+
};
|
17
|
+
|
18
|
+
export async function canClaim(
|
19
|
+
options: BaseTransactionOptions<CanClaimParams>,
|
20
|
+
): Promise<CanClaimResult> {
|
21
|
+
const [conditionId, { quantity, currency, pricePerToken, allowlistProof }] =
|
22
|
+
await Promise.all([
|
23
|
+
getActiveClaimConditionId({
|
24
|
+
contract: options.contract,
|
25
|
+
}),
|
26
|
+
getClaimParams({
|
27
|
+
contract: options.contract,
|
28
|
+
quantity: options.quantity,
|
29
|
+
to: options.claimer,
|
30
|
+
type: "erc721",
|
31
|
+
from: options.from,
|
32
|
+
}),
|
33
|
+
]);
|
34
|
+
try {
|
35
|
+
await verifyClaim({
|
36
|
+
contract: options.contract,
|
37
|
+
claimer: options.claimer,
|
38
|
+
quantity,
|
39
|
+
currency,
|
40
|
+
pricePerToken,
|
41
|
+
allowlistProof,
|
42
|
+
conditionId,
|
43
|
+
});
|
44
|
+
return {
|
45
|
+
result: true,
|
46
|
+
};
|
47
|
+
} catch (error) {
|
48
|
+
return {
|
49
|
+
result: false,
|
50
|
+
reason: await extractErrorResult({ error, contract: options.contract }),
|
51
|
+
};
|
52
|
+
}
|
53
|
+
}
|
@@ -517,6 +517,11 @@ function BuyScreenContent(props: BuyScreenContentProps) {
|
|
517
517
|
screen.id === "buy-with-fiat") &&
|
518
518
|
payer && (
|
519
519
|
<TokenSelectedLayout
|
520
|
+
disabled={
|
521
|
+
("prefillBuy" in payOptions &&
|
522
|
+
payOptions.prefillBuy?.allowEdits?.amount === false) ||
|
523
|
+
payOptions.mode !== "fund_wallet"
|
524
|
+
}
|
520
525
|
title={props.title}
|
521
526
|
selectedChain={toChain}
|
522
527
|
selectedToken={toToken}
|
@@ -651,6 +656,7 @@ function SelectedTokenInfo(props: {
|
|
651
656
|
tokenAmount: string;
|
652
657
|
setTokenAmount: (amount: string) => void;
|
653
658
|
client: ThirdwebClient;
|
659
|
+
disabled?: boolean;
|
654
660
|
}) {
|
655
661
|
const getWidth = () => {
|
656
662
|
let chars = props.tokenAmount.replace(".", "").length;
|
@@ -680,7 +686,7 @@ function SelectedTokenInfo(props: {
|
|
680
686
|
type="text"
|
681
687
|
data-placeholder={props.tokenAmount === ""}
|
682
688
|
value={props.tokenAmount || "0"}
|
683
|
-
disabled={
|
689
|
+
disabled={props.disabled}
|
684
690
|
onClick={(e) => {
|
685
691
|
// put cursor at the end of the input
|
686
692
|
if (props.tokenAmount === "") {
|
@@ -865,8 +871,13 @@ function MainScreen(props: {
|
|
865
871
|
}}
|
866
872
|
freezeAmount={payOptions.prefillBuy?.allowEdits?.amount === false}
|
867
873
|
freezeChainAndToken={
|
868
|
-
payOptions.prefillBuy?.allowEdits?.chain === false &&
|
869
|
-
|
874
|
+
(payOptions.prefillBuy?.allowEdits?.chain === false &&
|
875
|
+
payOptions.prefillBuy?.allowEdits?.token === false) ||
|
876
|
+
(payOptions.buyWithCrypto !== false &&
|
877
|
+
payOptions.buyWithCrypto?.prefillSource?.allowEdits?.token ===
|
878
|
+
false &&
|
879
|
+
payOptions.buyWithCrypto?.prefillSource?.allowEdits?.chain ===
|
880
|
+
false)
|
870
881
|
}
|
871
882
|
token={toToken}
|
872
883
|
chain={toChain}
|
@@ -924,6 +935,7 @@ function TokenSelectedLayout(props: {
|
|
924
935
|
selectedChain: Chain;
|
925
936
|
client: ThirdwebClient;
|
926
937
|
onBack: () => void;
|
938
|
+
disabled?: boolean;
|
927
939
|
}) {
|
928
940
|
return (
|
929
941
|
<Container>
|
@@ -944,6 +956,7 @@ function TokenSelectedLayout(props: {
|
|
944
956
|
tokenAmount={props.tokenAmount}
|
945
957
|
setTokenAmount={props.setTokenAmount}
|
946
958
|
client={props.client}
|
959
|
+
disabled={props.disabled}
|
947
960
|
/>
|
948
961
|
|
949
962
|
<Spacer y="md" />
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import styled from "@emotion/styled";
|
2
|
+
import { ChevronRightIcon } from "@radix-ui/react-icons";
|
2
3
|
import { useState } from "react";
|
3
4
|
import type { Chain } from "../../../../../../chains/types.js";
|
4
5
|
import type { ThirdwebClient } from "../../../../../../client/client.js";
|
@@ -22,7 +23,7 @@ import { Container } from "../../../components/basic.js";
|
|
22
23
|
import { Button } from "../../../components/buttons.js";
|
23
24
|
import { Text } from "../../../components/text.js";
|
24
25
|
import { Blobbie } from "../../Blobbie.js";
|
25
|
-
import {
|
26
|
+
import { FiatValue } from "./swap/FiatValue.js";
|
26
27
|
import type { TokenBalance } from "./swap/PaymentSelectionScreen.js";
|
27
28
|
|
28
29
|
export function WalletRowWithBalances(props: {
|
@@ -100,23 +101,29 @@ function TokenBalanceRow(props: {
|
|
100
101
|
onClick={() => onClick(tokenBalance.token, wallet)}
|
101
102
|
variant="secondary"
|
102
103
|
>
|
103
|
-
<
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
<
|
111
|
-
|
112
|
-
|
113
|
-
|
104
|
+
<Container flex="row" center="y" gap="md">
|
105
|
+
<TokenIcon
|
106
|
+
token={tokenBalance.token}
|
107
|
+
chain={tokenBalance.chain}
|
108
|
+
size="md"
|
109
|
+
client={client}
|
110
|
+
/>
|
111
|
+
<Container flex="column" gap="3xs">
|
112
|
+
<Text size="xs" color="primaryText">
|
113
|
+
{tokenBalance.token.symbol}
|
114
|
+
</Text>
|
115
|
+
{chainInfo && <Text size="xs">{chainInfo.name}</Text>}
|
116
|
+
</Container>
|
114
117
|
</Container>
|
115
|
-
<
|
116
|
-
|
117
|
-
|
118
|
-
{
|
119
|
-
|
118
|
+
<Container flex="row" center="y" gap="3xs" color="secondaryText">
|
119
|
+
<FiatValue
|
120
|
+
tokenAmount={tokenBalance.balance.displayValue}
|
121
|
+
token={tokenBalance.token}
|
122
|
+
chain={tokenBalance.chain}
|
123
|
+
client={client}
|
124
|
+
size="xs"
|
125
|
+
/>
|
126
|
+
<ChevronRightIcon width={iconSize.md} height={iconSize.md} />
|
120
127
|
</Container>
|
121
128
|
</StyledButton>
|
122
129
|
);
|
@@ -149,7 +156,7 @@ export function WalletRow(props: {
|
|
149
156
|
width={props.iconSize ? iconSize[props.iconSize] : iconSize.md}
|
150
157
|
height={props.iconSize ? iconSize[props.iconSize] : iconSize.md}
|
151
158
|
style={{
|
152
|
-
borderRadius:
|
159
|
+
borderRadius: radius.sm,
|
153
160
|
overflow: "hidden",
|
154
161
|
border: `1px solid ${theme.colors.borderColor}`,
|
155
162
|
}}
|
@@ -166,7 +173,7 @@ export function WalletRow(props: {
|
|
166
173
|
style={{
|
167
174
|
width: iconSize.md,
|
168
175
|
height: iconSize.md,
|
169
|
-
borderRadius:
|
176
|
+
borderRadius: radius.sm,
|
170
177
|
overflow: "hidden",
|
171
178
|
border: `1px solid ${theme.colors.borderColor}`,
|
172
179
|
}}
|
@@ -186,7 +193,7 @@ const StyledButton = /* @__PURE__ */ styled(Button)((_) => {
|
|
186
193
|
const theme = useCustomTheme();
|
187
194
|
return {
|
188
195
|
background: theme.colors.tertiaryBg,
|
189
|
-
justifyContent: "
|
196
|
+
justifyContent: "space-between",
|
190
197
|
flexDirection: "row",
|
191
198
|
padding: spacing.sm,
|
192
199
|
gap: spacing.sm,
|
@@ -166,25 +166,37 @@ export function PaymentSelectionScreen(props: {
|
|
166
166
|
return <LoadingScreen />;
|
167
167
|
}
|
168
168
|
|
169
|
+
const filteredWallets = Array.from(walletsAndBalances.data?.entries() || [])
|
170
|
+
.filter(([w]) => !props.hiddenWallets?.includes(w.id))
|
171
|
+
.filter(([, balances]) => {
|
172
|
+
const hasEnoughBalance = balances.some((b) => b.balance.value > 0);
|
173
|
+
return hasEnoughBalance;
|
174
|
+
});
|
175
|
+
|
169
176
|
return (
|
170
177
|
<Container>
|
171
178
|
<Container flex="column" gap="xs">
|
172
|
-
{
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
179
|
+
{filteredWallets.length === 0 && (
|
180
|
+
<Container flex="column" gap="xs" py="md">
|
181
|
+
<Text size="xs" color="secondaryText" center>
|
182
|
+
<i>Insufficient funds in connected wallets</i>
|
183
|
+
</Text>
|
184
|
+
</Container>
|
185
|
+
)}
|
186
|
+
{filteredWallets.map(([w, balances]) => {
|
187
|
+
const address = w.getAccount()?.address;
|
188
|
+
if (!address) return null;
|
189
|
+
return (
|
190
|
+
<WalletRowWithBalances
|
191
|
+
key={w.id}
|
192
|
+
wallet={w}
|
193
|
+
balances={balances}
|
194
|
+
client={props.client}
|
195
|
+
address={address}
|
196
|
+
onClick={props.onSelect}
|
197
|
+
/>
|
198
|
+
);
|
199
|
+
})}
|
188
200
|
{!hideConnectButton && (
|
189
201
|
<Button
|
190
202
|
variant="secondary"
|
@@ -13,7 +13,12 @@ export const defaultMessage = "Unable to get price quote";
|
|
13
13
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
14
14
|
export function getErrorMessage(err: any): ApiError {
|
15
15
|
if (typeof err.error === "object" && err.error.code) {
|
16
|
-
|
16
|
+
if (err.error.code === "MINIMUM_PURCHASE_AMOUNT") {
|
17
|
+
return {
|
18
|
+
code: "MINIMUM_PURCHASE_AMOUNT",
|
19
|
+
message: "Purchase amount is too low",
|
20
|
+
};
|
21
|
+
}
|
17
22
|
}
|
18
23
|
return {
|
19
24
|
code: "UNABLE_TO_GET_PRICE_QUOTE",
|
@@ -78,7 +78,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("prepareengineTransaction", () => {
|
|
78
78
|
{
|
79
79
|
"data": "0xa9059cbb00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000000000000000000000000000056bc75e2d63100000",
|
80
80
|
"from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
81
|
-
"gas":
|
81
|
+
"gas": 64340n,
|
82
82
|
"nonce": 0n,
|
83
83
|
"to": "${erc20Contract.address}",
|
84
84
|
"value": 0n,
|