@0xsequence/marketplace-sdk 0.3.2 → 0.3.4
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/{chunk-NII6JJGH.js → chunk-3CXEYH2I.js} +5 -3
- package/dist/chunk-3CXEYH2I.js.map +1 -0
- package/dist/{chunk-GJAKQ5Q3.js → chunk-53Q7BNZH.js} +8 -2
- package/dist/chunk-53Q7BNZH.js.map +1 -0
- package/dist/{chunk-O7UQGT43.js → chunk-6LQST3KZ.js} +553 -283
- package/dist/chunk-6LQST3KZ.js.map +1 -0
- package/dist/{chunk-GZG2QO64.js → chunk-D3HRXVYJ.js} +72 -21
- package/dist/chunk-D3HRXVYJ.js.map +1 -0
- package/dist/{chunk-4YU2UPYH.js → chunk-FFCNYF3S.js} +61 -61
- package/dist/chunk-FFCNYF3S.js.map +1 -0
- package/dist/chunk-G2FYRJMK.js +38 -0
- package/dist/chunk-G2FYRJMK.js.map +1 -0
- package/dist/{chunk-WA433WAJ.js → chunk-L6GSYPCR.js} +20 -6
- package/dist/chunk-L6GSYPCR.js.map +1 -0
- package/dist/{chunk-SPW24Y7I.js → chunk-OUZ42I6B.js} +7 -2
- package/dist/chunk-OUZ42I6B.js.map +1 -0
- package/dist/{chunk-22NLQ3AS.js → chunk-PMDJARYX.js} +1081 -980
- package/dist/chunk-PMDJARYX.js.map +1 -0
- package/dist/chunk-T2AMWIKD.js +277 -0
- package/dist/chunk-T2AMWIKD.js.map +1 -0
- package/dist/{chunk-G33554LK.js → chunk-WQCWBXBM.js} +8 -16
- package/dist/chunk-WQCWBXBM.js.map +1 -0
- package/dist/index.css +40 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +172 -71
- package/dist/index.js.map +1 -1
- package/dist/{marketplace.gen-BLP7822q.d.ts → marketplace.gen-jdKqutnd.d.ts} +57 -18
- package/dist/react/_internal/api/index.d.ts +4 -2
- package/dist/react/_internal/api/index.js +8 -3
- package/dist/react/_internal/index.d.ts +3 -3
- package/dist/react/_internal/index.js +9 -4
- package/dist/react/_internal/wagmi/index.js +2 -1
- package/dist/react/hooks/index.d.ts +285 -12
- package/dist/react/hooks/index.js +14 -5
- package/dist/react/index.css +29 -29
- package/dist/react/index.css.map +1 -1
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +17 -8
- package/dist/react/ssr/index.js +55 -4
- package/dist/react/ssr/index.js.map +1 -1
- package/dist/react/ui/components/index.css +13 -13
- package/dist/react/ui/components/index.css.map +1 -1
- package/dist/react/ui/components/index.d.ts +3 -3
- package/dist/react/ui/components/index.js +9 -8
- package/dist/react/ui/icons/index.js +1 -1
- package/dist/react/ui/icons/index.js.map +1 -1
- package/dist/react/ui/index.css +29 -29
- package/dist/react/ui/index.css.map +1 -1
- package/dist/react/ui/index.d.ts +3 -3
- package/dist/react/ui/index.js +9 -8
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +3 -2
- package/dist/react/ui/styles/index.d.ts +1 -1
- package/dist/{services-C9-lvWcC.d.ts → services-C2O-7p_M.d.ts} +2 -2
- package/dist/styles/index.css +40 -0
- package/dist/styles/index.css.map +1 -1
- package/dist/styles/index.d.ts +9 -2
- package/dist/styles/index.js +14 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +3 -2
- package/dist/{types-QqXjNuUP.d.ts → types-BlDoGvJV.d.ts} +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +2 -1
- package/package.json +18 -15
- package/src/react/_internal/api/marketplace.gen.ts +85 -20
- package/src/react/_internal/api/query-keys.ts +2 -0
- package/src/react/_internal/api/services.ts +4 -3
- package/src/react/_internal/api/zod-schema.ts +20 -0
- package/src/react/_internal/transaction-machine/execute-transaction.ts +311 -224
- package/src/react/_internal/transaction-machine/logger.ts +66 -0
- package/src/react/_internal/transaction-machine/useTransactionMachine.ts +69 -19
- package/src/react/_internal/wagmi/embedded.ts +2 -2
- package/src/react/hooks/index.ts +2 -0
- package/src/react/hooks/options/marketplaceConfigOptions.ts +6 -2
- package/src/react/hooks/useBuyCollectable.tsx +14 -8
- package/src/react/hooks/useCancelOrder.tsx +4 -3
- package/src/react/hooks/useCheckoutOptions.tsx +2 -2
- package/src/react/hooks/useConfig.tsx +2 -3
- package/src/react/hooks/useCountListingsForCollectible.tsx +64 -0
- package/src/react/hooks/useCountOffersForCollectible.tsx +64 -0
- package/src/react/hooks/useCreateListing.tsx +13 -14
- package/src/react/hooks/useCurrencies.tsx +9 -8
- package/src/react/hooks/useCurrency.tsx +6 -6
- package/src/react/hooks/useGenerateBuyTransaction.tsx +3 -3
- package/src/react/hooks/useMakeOffer.tsx +14 -13
- package/src/react/hooks/useRoyaltyPercentage.tsx +1 -1
- package/src/react/hooks/useSell.tsx +12 -12
- package/src/react/hooks/useTransferTokens.tsx +2 -1
- package/src/react/ui/components/_internals/action-button/ActionButton.tsx +3 -2
- package/src/react/ui/components/_internals/custom-select/CustomSelect.tsx +4 -4
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +2 -2
- package/src/react/ui/components/collectible-card/Footer.tsx +33 -29
- package/src/react/ui/icons/ArrowUp.tsx +1 -1
- package/src/react/ui/modals/BuyModal/_store.ts +8 -6
- package/src/react/ui/modals/BuyModal/index.tsx +120 -81
- package/src/react/ui/modals/CreateListingModal/_store.ts +1 -0
- package/src/react/ui/modals/CreateListingModal/index.tsx +34 -14
- package/src/react/ui/modals/MakeOfferModal/_store.ts +2 -0
- package/src/react/ui/modals/MakeOfferModal/index.tsx +21 -11
- package/src/react/ui/modals/SellModal/index.tsx +21 -13
- package/src/react/ui/modals/SuccessfulPurchaseModal/_store.ts +1 -1
- package/src/react/ui/modals/SuccessfulPurchaseModal/index.tsx +1 -1
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +12 -7
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +2 -1
- package/src/react/ui/modals/TransferModal/_views/followWalletInstructions/index.tsx +2 -2
- package/src/react/ui/modals/TransferModal/styles.css.ts +1 -1
- package/src/react/ui/modals/_internal/components/actionModal/ErrorModal.tsx +1 -1
- package/src/react/ui/modals/_internal/components/actionModal/LoadingModal.tsx +1 -1
- package/src/react/ui/modals/_internal/components/alertMessage/index.tsx +7 -2
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +2 -7
- package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +2 -1
- package/src/react/ui/modals/_internal/components/floorPriceText/index.tsx +1 -0
- package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +42 -102
- package/src/react/ui/modals/_internal/components/switchChainModal/styles.css.ts +1 -1
- package/src/react/ui/modals/_internal/components/timeAgo/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +32 -11
- package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +2 -2
- package/src/react/ui/modals/_internal/components/transactionHeader/index.tsx +14 -2
- package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +17 -5
- package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +12 -4
- package/src/react/ui/modals/_internal/components/transactionStatusModal/styles.css.ts +1 -1
- package/src/react/ui/modals/modal-provider.tsx +3 -3
- package/src/styles/index.ts +3 -0
- package/src/utils/_internal/error/base.ts +32 -0
- package/src/utils/_internal/error/context.ts +13 -0
- package/src/utils/_internal/error/transaction.ts +369 -0
- package/src/utils/get-public-rpc-client.ts +4 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/tsup.config.ts +3 -0
- package/dist/chess-tile-6BS5MQT5.png +0 -0
- package/dist/chunk-22NLQ3AS.js.map +0 -1
- package/dist/chunk-4YU2UPYH.js.map +0 -1
- package/dist/chunk-G33554LK.js.map +0 -1
- package/dist/chunk-GJAKQ5Q3.js.map +0 -1
- package/dist/chunk-GZG2QO64.js.map +0 -1
- package/dist/chunk-NII6JJGH.js.map +0 -1
- package/dist/chunk-O7UQGT43.js.map +0 -1
- package/dist/chunk-SPW24Y7I.js.map +0 -1
- package/dist/chunk-WA433WAJ.js.map +0 -1
|
@@ -7,12 +7,13 @@ import type {
|
|
|
7
7
|
TypedDataDomain,
|
|
8
8
|
WalletClient,
|
|
9
9
|
} from 'viem';
|
|
10
|
-
import { avalanche } from 'viem/chains';
|
|
10
|
+
import { avalanche, optimism } from 'viem/chains';
|
|
11
11
|
import {
|
|
12
12
|
type AdditionalFee,
|
|
13
13
|
type SequenceMarketplace,
|
|
14
14
|
TransactionSwapProvider,
|
|
15
15
|
type WalletKind,
|
|
16
|
+
WebrpcError,
|
|
16
17
|
getMarketplaceClient,
|
|
17
18
|
} from '..';
|
|
18
19
|
import {
|
|
@@ -26,6 +27,29 @@ import {
|
|
|
26
27
|
type Step,
|
|
27
28
|
StepType,
|
|
28
29
|
} from '../../../types';
|
|
30
|
+
import {
|
|
31
|
+
ChainIdUnavailableError,
|
|
32
|
+
ChainSwitchError,
|
|
33
|
+
CheckoutOptionsError,
|
|
34
|
+
InvalidSignatureStepError,
|
|
35
|
+
MissingPostStepError,
|
|
36
|
+
MissingSignatureDataError,
|
|
37
|
+
MissingStepDataError,
|
|
38
|
+
NoExecutionStepError,
|
|
39
|
+
NoStepsFoundError,
|
|
40
|
+
NoWalletConnectedError,
|
|
41
|
+
OrderNotFoundError,
|
|
42
|
+
OrdersFetchError,
|
|
43
|
+
PaymentModalError,
|
|
44
|
+
PaymentModalTransactionError,
|
|
45
|
+
StepExecutionError,
|
|
46
|
+
StepGenerationError,
|
|
47
|
+
TransactionError,
|
|
48
|
+
TransactionReceiptError,
|
|
49
|
+
UnexpectedStepsError,
|
|
50
|
+
UnknownTransactionTypeError,
|
|
51
|
+
} from '../../../utils/_internal/error/transaction';
|
|
52
|
+
import { type TransactionLogger, createLogger } from './logger';
|
|
29
53
|
|
|
30
54
|
export enum TransactionState {
|
|
31
55
|
IDLE = 'IDLE',
|
|
@@ -60,7 +84,6 @@ interface StateConfig {
|
|
|
60
84
|
config: TransactionConfig;
|
|
61
85
|
onTransactionSent?: (hash: Hash) => void;
|
|
62
86
|
onSuccess?: (hash: Hash) => void;
|
|
63
|
-
onError?: (error: Error) => void;
|
|
64
87
|
}
|
|
65
88
|
|
|
66
89
|
export interface BuyInput {
|
|
@@ -91,6 +114,13 @@ export interface CancelInput {
|
|
|
91
114
|
marketplace: MarketplaceKind;
|
|
92
115
|
}
|
|
93
116
|
|
|
117
|
+
export type Input =
|
|
118
|
+
| BuyInput
|
|
119
|
+
| SellInput
|
|
120
|
+
| ListingInput
|
|
121
|
+
| OfferInput
|
|
122
|
+
| CancelInput;
|
|
123
|
+
|
|
94
124
|
type TransactionInput =
|
|
95
125
|
| {
|
|
96
126
|
type: TransactionType.BUY;
|
|
@@ -113,13 +143,6 @@ type TransactionInput =
|
|
|
113
143
|
props: CancelInput;
|
|
114
144
|
};
|
|
115
145
|
|
|
116
|
-
interface StateConfig {
|
|
117
|
-
config: TransactionConfig;
|
|
118
|
-
onTransactionSent?: (hash: Hash) => void;
|
|
119
|
-
onSuccess?: (hash: Hash) => void;
|
|
120
|
-
onError?: (error: Error) => void;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
146
|
interface TransactionStep {
|
|
124
147
|
isPending: boolean;
|
|
125
148
|
isExecuting: boolean;
|
|
@@ -140,15 +163,12 @@ export interface TransactionSteps {
|
|
|
140
163
|
};
|
|
141
164
|
}
|
|
142
165
|
|
|
143
|
-
const debug = (message: string, data?: any) => {
|
|
144
|
-
console.debug(`[TransactionMachine] ${message}`, data || '');
|
|
145
|
-
};
|
|
146
|
-
|
|
147
166
|
export class TransactionMachine {
|
|
148
167
|
private currentState: TransactionState;
|
|
168
|
+
private readonly logger: TransactionLogger;
|
|
149
169
|
private marketplaceClient: SequenceMarketplace;
|
|
150
170
|
private memoizedSteps: TransactionSteps | null = null;
|
|
151
|
-
private lastProps:
|
|
171
|
+
private lastProps: Input | null = null;
|
|
152
172
|
|
|
153
173
|
constructor(
|
|
154
174
|
private readonly config: StateConfig,
|
|
@@ -160,6 +180,7 @@ export class TransactionMachine {
|
|
|
160
180
|
private readonly switchChainFn: (chainId: string) => Promise<void>,
|
|
161
181
|
) {
|
|
162
182
|
this.currentState = TransactionState.IDLE;
|
|
183
|
+
this.logger = createLogger('TransactionMachine');
|
|
163
184
|
this.marketplaceClient = getMarketplaceClient(
|
|
164
185
|
config.config.chainId,
|
|
165
186
|
config.config.sdkConfig,
|
|
@@ -169,7 +190,7 @@ export class TransactionMachine {
|
|
|
169
190
|
private getAccount() {
|
|
170
191
|
const account = this.walletClient.account;
|
|
171
192
|
if (!account) {
|
|
172
|
-
throw new
|
|
193
|
+
throw new NoWalletConnectedError();
|
|
173
194
|
}
|
|
174
195
|
return account;
|
|
175
196
|
}
|
|
@@ -187,10 +208,11 @@ export class TransactionMachine {
|
|
|
187
208
|
this.getChainId() === Number(collection.chainId),
|
|
188
209
|
);
|
|
189
210
|
|
|
190
|
-
const
|
|
191
|
-
this.getChainId() === avalanche.id
|
|
192
|
-
|
|
193
|
-
|
|
211
|
+
const avalancheOrOptimism =
|
|
212
|
+
this.getChainId() === avalanche.id || this.getChainId() === optimism.id;
|
|
213
|
+
const receiver = avalancheOrOptimism
|
|
214
|
+
? avalancheAndOptimismPlatformFeeRecipient
|
|
215
|
+
: defaultPlatformFeeRecipient;
|
|
194
216
|
|
|
195
217
|
const percentageToBPS = (percentage: string | number) =>
|
|
196
218
|
(Number(percentage) * 10000) / 100;
|
|
@@ -211,97 +233,108 @@ export class TransactionMachine {
|
|
|
211
233
|
type,
|
|
212
234
|
props,
|
|
213
235
|
}: TransactionInput): Promise<Step[]> {
|
|
214
|
-
debug('Generating steps', { type, props });
|
|
236
|
+
this.logger.debug('Generating steps', { type, props });
|
|
215
237
|
const { collectionAddress } = this.config.config;
|
|
216
238
|
const address = this.getAccountAddress();
|
|
217
|
-
switch (type) {
|
|
218
|
-
case TransactionType.BUY:
|
|
219
|
-
return this.marketplaceClient
|
|
220
|
-
.generateBuyTransaction({
|
|
221
|
-
collectionAddress,
|
|
222
|
-
buyer: address,
|
|
223
|
-
walletType: this.config.config.walletKind,
|
|
224
|
-
marketplace: props.marketplace,
|
|
225
|
-
ordersData: [
|
|
226
|
-
{
|
|
227
|
-
orderId: props.orderId,
|
|
228
|
-
quantity: props.quantity || '1',
|
|
229
|
-
},
|
|
230
|
-
],
|
|
231
|
-
additionalFees: [this.getMarketplaceFee(collectionAddress)],
|
|
232
|
-
})
|
|
233
|
-
.then((resp) => resp.steps);
|
|
234
|
-
|
|
235
|
-
case TransactionType.SELL:
|
|
236
|
-
return this.marketplaceClient
|
|
237
|
-
.generateSellTransaction({
|
|
238
|
-
collectionAddress,
|
|
239
|
-
seller: address,
|
|
240
|
-
walletType: this.config.config.walletKind,
|
|
241
|
-
marketplace: props.marketplace,
|
|
242
|
-
ordersData: [
|
|
243
|
-
{
|
|
244
|
-
orderId: props.orderId,
|
|
245
|
-
quantity: props.quantity || '1',
|
|
246
|
-
},
|
|
247
|
-
],
|
|
248
|
-
additionalFees: [],
|
|
249
|
-
})
|
|
250
|
-
.then((resp) => resp.steps);
|
|
251
|
-
|
|
252
|
-
case TransactionType.LISTING:
|
|
253
|
-
return this.marketplaceClient
|
|
254
|
-
.generateListingTransaction({
|
|
255
|
-
collectionAddress,
|
|
256
|
-
owner: address,
|
|
257
|
-
walletType: this.config.config.walletKind,
|
|
258
|
-
contractType: props.contractType,
|
|
259
|
-
orderbook: OrderbookKind.sequence_marketplace_v2,
|
|
260
|
-
listing: props.listing,
|
|
261
|
-
})
|
|
262
|
-
.then((resp) => resp.steps);
|
|
263
|
-
|
|
264
|
-
case TransactionType.OFFER:
|
|
265
|
-
return this.marketplaceClient
|
|
266
|
-
.generateOfferTransaction({
|
|
267
|
-
collectionAddress,
|
|
268
|
-
maker: address,
|
|
269
|
-
walletType: this.config.config.walletKind,
|
|
270
|
-
contractType: props.contractType,
|
|
271
|
-
orderbook: OrderbookKind.sequence_marketplace_v2,
|
|
272
|
-
offer: props.offer,
|
|
273
|
-
})
|
|
274
|
-
.then((resp) => resp.steps);
|
|
275
|
-
|
|
276
|
-
case TransactionType.CANCEL:
|
|
277
|
-
return this.marketplaceClient
|
|
278
|
-
.generateCancelTransaction({
|
|
279
|
-
collectionAddress,
|
|
280
|
-
maker: address,
|
|
281
|
-
marketplace: props.marketplace,
|
|
282
|
-
orderId: props.orderId,
|
|
283
|
-
})
|
|
284
|
-
.then((resp) => resp.steps);
|
|
285
239
|
|
|
286
|
-
|
|
287
|
-
|
|
240
|
+
try {
|
|
241
|
+
switch (type) {
|
|
242
|
+
case TransactionType.BUY:
|
|
243
|
+
return await this.marketplaceClient
|
|
244
|
+
.generateBuyTransaction({
|
|
245
|
+
collectionAddress,
|
|
246
|
+
buyer: address,
|
|
247
|
+
walletType: this.config.config.walletKind,
|
|
248
|
+
marketplace: props.marketplace,
|
|
249
|
+
ordersData: [
|
|
250
|
+
{
|
|
251
|
+
orderId: props.orderId,
|
|
252
|
+
quantity: props.quantity || '1',
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
additionalFees: [this.getMarketplaceFee(collectionAddress)],
|
|
256
|
+
})
|
|
257
|
+
.then((resp) => resp.steps);
|
|
258
|
+
|
|
259
|
+
case TransactionType.SELL:
|
|
260
|
+
return await this.marketplaceClient
|
|
261
|
+
.generateSellTransaction({
|
|
262
|
+
collectionAddress,
|
|
263
|
+
seller: address,
|
|
264
|
+
walletType: this.config.config.walletKind,
|
|
265
|
+
marketplace: props.marketplace,
|
|
266
|
+
ordersData: [
|
|
267
|
+
{
|
|
268
|
+
orderId: props.orderId,
|
|
269
|
+
quantity: props.quantity || '1',
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
additionalFees: [],
|
|
273
|
+
})
|
|
274
|
+
.then((resp) => resp.steps);
|
|
275
|
+
|
|
276
|
+
case TransactionType.LISTING:
|
|
277
|
+
return await this.marketplaceClient
|
|
278
|
+
.generateListingTransaction({
|
|
279
|
+
collectionAddress,
|
|
280
|
+
owner: address,
|
|
281
|
+
walletType: this.config.config.walletKind,
|
|
282
|
+
contractType: props.contractType,
|
|
283
|
+
orderbook: OrderbookKind.sequence_marketplace_v2,
|
|
284
|
+
listing: props.listing,
|
|
285
|
+
})
|
|
286
|
+
.then((resp) => resp.steps);
|
|
287
|
+
|
|
288
|
+
case TransactionType.OFFER:
|
|
289
|
+
return await this.marketplaceClient
|
|
290
|
+
.generateOfferTransaction({
|
|
291
|
+
collectionAddress,
|
|
292
|
+
maker: address,
|
|
293
|
+
walletType: this.config.config.walletKind,
|
|
294
|
+
contractType: props.contractType,
|
|
295
|
+
orderbook: OrderbookKind.sequence_marketplace_v2,
|
|
296
|
+
offer: props.offer,
|
|
297
|
+
})
|
|
298
|
+
.then((resp) => resp.steps);
|
|
299
|
+
|
|
300
|
+
case TransactionType.CANCEL:
|
|
301
|
+
return await this.marketplaceClient
|
|
302
|
+
.generateCancelTransaction({
|
|
303
|
+
collectionAddress,
|
|
304
|
+
maker: address,
|
|
305
|
+
marketplace: props.marketplace,
|
|
306
|
+
orderId: props.orderId,
|
|
307
|
+
})
|
|
308
|
+
.then((resp) => resp.steps);
|
|
309
|
+
default:
|
|
310
|
+
throw new UnknownTransactionTypeError(type);
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
if (error instanceof WebrpcError) {
|
|
314
|
+
throw new StepGenerationError(type, error);
|
|
315
|
+
}
|
|
316
|
+
throw error;
|
|
288
317
|
}
|
|
289
318
|
}
|
|
290
319
|
|
|
291
320
|
private clearMemoizedSteps() {
|
|
292
|
-
debug('Clearing memoized steps');
|
|
321
|
+
this.logger.debug('Clearing memoized steps');
|
|
293
322
|
this.memoizedSteps = null;
|
|
294
323
|
this.lastProps = null;
|
|
295
324
|
}
|
|
296
325
|
|
|
297
326
|
private async transition(newState: TransactionState) {
|
|
298
|
-
|
|
327
|
+
this.logger.state(this.currentState, newState);
|
|
299
328
|
this.currentState = newState;
|
|
300
329
|
this.clearMemoizedSteps();
|
|
301
330
|
}
|
|
302
331
|
|
|
303
|
-
private getChainId() {
|
|
304
|
-
|
|
332
|
+
private getChainId(): number {
|
|
333
|
+
const chainId = this.walletClient.chain?.id;
|
|
334
|
+
if (!chainId) {
|
|
335
|
+
throw new ChainIdUnavailableError();
|
|
336
|
+
}
|
|
337
|
+
return chainId;
|
|
305
338
|
}
|
|
306
339
|
|
|
307
340
|
private getChainForTransaction() {
|
|
@@ -316,42 +349,44 @@ export class TransactionMachine {
|
|
|
316
349
|
}
|
|
317
350
|
|
|
318
351
|
private async switchChain(): Promise<void> {
|
|
352
|
+
this.logger.debug('Checking chain', {
|
|
353
|
+
currentChain: this.getChainId(),
|
|
354
|
+
targetChain: Number(this.config.config.chainId),
|
|
355
|
+
});
|
|
356
|
+
|
|
319
357
|
if (!this.isOnCorrectChain()) {
|
|
358
|
+
const currentChain = this.getChainId();
|
|
359
|
+
const targetChain = Number(this.config.config.chainId);
|
|
360
|
+
|
|
320
361
|
await this.transition(TransactionState.SWITCH_CHAIN);
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
362
|
+
try {
|
|
363
|
+
await this.switchChainFn(this.config.config.chainId);
|
|
364
|
+
await this.walletClient.switchChain({
|
|
365
|
+
id: Number(this.config.config.chainId),
|
|
366
|
+
});
|
|
367
|
+
this.logger.debug('Switched chain');
|
|
368
|
+
} catch (error) {
|
|
369
|
+
throw new ChainSwitchError(currentChain, targetChain);
|
|
370
|
+
}
|
|
326
371
|
}
|
|
327
372
|
}
|
|
328
373
|
|
|
329
|
-
async start(
|
|
330
|
-
debug('Starting transaction', props);
|
|
331
|
-
try {
|
|
332
|
-
await this.transition(TransactionState.CHECKING_STEPS);
|
|
333
|
-
const { type } = this.config.config;
|
|
334
|
-
|
|
335
|
-
const steps = await this.generateSteps({
|
|
336
|
-
type,
|
|
337
|
-
props,
|
|
338
|
-
} as TransactionInput);
|
|
339
|
-
|
|
340
|
-
for (const step of steps) {
|
|
341
|
-
try {
|
|
342
|
-
await this.executeStep({ step, props });
|
|
343
|
-
} catch (error) {
|
|
344
|
-
await this.transition(TransactionState.ERROR);
|
|
345
|
-
throw error;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
374
|
+
async start(props: Input) {
|
|
375
|
+
this.logger.debug('Starting transaction', props);
|
|
348
376
|
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
377
|
+
await this.transition(TransactionState.CHECKING_STEPS);
|
|
378
|
+
const { type } = this.config.config;
|
|
379
|
+
|
|
380
|
+
const steps = await this.generateSteps({
|
|
381
|
+
type,
|
|
382
|
+
props,
|
|
383
|
+
} as TransactionInput);
|
|
384
|
+
|
|
385
|
+
for (const step of steps) {
|
|
386
|
+
await this.executeStep({ step, props });
|
|
354
387
|
}
|
|
388
|
+
|
|
389
|
+
await this.transition(TransactionState.SUCCESS);
|
|
355
390
|
}
|
|
356
391
|
|
|
357
392
|
private async handleTransactionSuccess(hash?: Hash) {
|
|
@@ -363,39 +398,53 @@ export class TransactionMachine {
|
|
|
363
398
|
await this.transition(TransactionState.CONFIRMING);
|
|
364
399
|
this.config.onTransactionSent?.(hash);
|
|
365
400
|
|
|
366
|
-
|
|
367
|
-
|
|
401
|
+
try {
|
|
402
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
403
|
+
hash,
|
|
404
|
+
});
|
|
405
|
+
this.logger.debug('Transaction confirmed', receipt);
|
|
368
406
|
|
|
369
|
-
|
|
370
|
-
|
|
407
|
+
await this.transition(TransactionState.SUCCESS);
|
|
408
|
+
this.config.onSuccess?.(hash);
|
|
409
|
+
} catch (error) {
|
|
410
|
+
throw new TransactionReceiptError(hash, error as Error);
|
|
411
|
+
}
|
|
371
412
|
}
|
|
372
413
|
|
|
373
414
|
private async executeTransaction(step: Step): Promise<Hash> {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
415
|
+
try {
|
|
416
|
+
const transactionData = {
|
|
417
|
+
account: this.getAccount(),
|
|
418
|
+
chain: this.getChainForTransaction(),
|
|
419
|
+
to: step.to as Hex,
|
|
420
|
+
data: step.data as Hex,
|
|
421
|
+
value: BigInt(step.value || '0'),
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
this.logger.debug('Executing transaction', transactionData);
|
|
425
|
+
const hash = await this.walletClient.sendTransaction(transactionData);
|
|
426
|
+
this.logger.debug('Transaction submitted', { hash });
|
|
427
|
+
|
|
428
|
+
await this.handleTransactionSuccess(hash);
|
|
429
|
+
return hash;
|
|
430
|
+
} catch (error) {
|
|
431
|
+
throw new StepExecutionError(step.id, error as Error);
|
|
432
|
+
}
|
|
386
433
|
}
|
|
387
434
|
|
|
388
435
|
private async executeSignature(step: Step) {
|
|
389
|
-
debug('Executing signature', { stepId: step.id });
|
|
390
|
-
let signature: Hex;
|
|
436
|
+
this.logger.debug('Executing signature', { stepId: step.id });
|
|
391
437
|
if (!step.post) {
|
|
392
|
-
throw new
|
|
438
|
+
throw new MissingPostStepError();
|
|
393
439
|
}
|
|
440
|
+
|
|
441
|
+
let signature: Hex;
|
|
442
|
+
if (!step.signature) {
|
|
443
|
+
throw new MissingSignatureDataError();
|
|
444
|
+
}
|
|
445
|
+
|
|
394
446
|
switch (step.id) {
|
|
395
447
|
case StepType.signEIP712:
|
|
396
|
-
if (!step.signature) {
|
|
397
|
-
throw new Error('Missing signature data');
|
|
398
|
-
}
|
|
399
448
|
signature = await this.walletClient.signTypedData({
|
|
400
449
|
domain: step.signature.domain as TypedDataDomain,
|
|
401
450
|
types: step.signature.types,
|
|
@@ -411,7 +460,7 @@ export class TransactionMachine {
|
|
|
411
460
|
});
|
|
412
461
|
break;
|
|
413
462
|
default:
|
|
414
|
-
throw new
|
|
463
|
+
throw new InvalidSignatureStepError(step.id);
|
|
415
464
|
}
|
|
416
465
|
|
|
417
466
|
await this.marketplaceClient.execute({
|
|
@@ -429,12 +478,15 @@ export class TransactionMachine {
|
|
|
429
478
|
this.openSelectPaymentModal({
|
|
430
479
|
...settings,
|
|
431
480
|
onSuccess: async (hash: string) => {
|
|
432
|
-
|
|
433
|
-
|
|
481
|
+
try {
|
|
482
|
+
await this.handleTransactionSuccess(hash as Hash);
|
|
483
|
+
resolve();
|
|
484
|
+
} catch (error) {
|
|
485
|
+
reject(error);
|
|
486
|
+
}
|
|
434
487
|
},
|
|
435
488
|
onError: (error: Error) => {
|
|
436
|
-
|
|
437
|
-
reject(error);
|
|
489
|
+
reject(new PaymentModalError(error));
|
|
438
490
|
},
|
|
439
491
|
});
|
|
440
492
|
});
|
|
@@ -447,56 +499,85 @@ export class TransactionMachine {
|
|
|
447
499
|
step: Step;
|
|
448
500
|
props: BuyInput;
|
|
449
501
|
}) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
orders
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
502
|
+
try {
|
|
503
|
+
await this.transition(TransactionState.EXECUTING_TRANSACTION);
|
|
504
|
+
|
|
505
|
+
try {
|
|
506
|
+
const [checkoutOptions, orders] = await Promise.all([
|
|
507
|
+
this.marketplaceClient
|
|
508
|
+
.checkoutOptionsMarketplace({
|
|
509
|
+
wallet: this.getAccountAddress(),
|
|
510
|
+
orders: [
|
|
511
|
+
{
|
|
512
|
+
contractAddress: this.config.config.collectionAddress,
|
|
513
|
+
orderId: props.orderId,
|
|
514
|
+
marketplace: props.marketplace,
|
|
515
|
+
},
|
|
516
|
+
],
|
|
517
|
+
additionalFee: Number(
|
|
518
|
+
this.getMarketplaceFee(this.config.config.collectionAddress)
|
|
519
|
+
.amount,
|
|
520
|
+
),
|
|
521
|
+
})
|
|
522
|
+
.catch((error) => {
|
|
523
|
+
throw new CheckoutOptionsError(error);
|
|
524
|
+
}),
|
|
525
|
+
this.marketplaceClient
|
|
526
|
+
.getOrders({
|
|
527
|
+
input: [
|
|
528
|
+
{
|
|
529
|
+
orderId: props.orderId,
|
|
530
|
+
marketplace: props.marketplace,
|
|
531
|
+
contractAddress: this.config.config.collectionAddress,
|
|
532
|
+
},
|
|
533
|
+
],
|
|
534
|
+
})
|
|
535
|
+
.catch((error) => {
|
|
536
|
+
throw new OrdersFetchError(props.orderId, error);
|
|
537
|
+
}),
|
|
538
|
+
]);
|
|
539
|
+
|
|
540
|
+
const order = orders.orders[0];
|
|
541
|
+
if (!order) {
|
|
542
|
+
throw new OrderNotFoundError(props.orderId);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const paymentModalProps = {
|
|
546
|
+
chain: this.getChainId()!,
|
|
547
|
+
collectibles: [
|
|
548
|
+
{
|
|
549
|
+
tokenId: order.tokenId,
|
|
550
|
+
quantity: props.quantity,
|
|
551
|
+
decimals: props.collectableDecimals,
|
|
552
|
+
},
|
|
553
|
+
],
|
|
554
|
+
currencyAddress: order.priceCurrencyAddress,
|
|
555
|
+
price: order.priceAmount,
|
|
556
|
+
targetContractAddress: step.to,
|
|
557
|
+
txData: step.data as Hex,
|
|
558
|
+
collectionAddress: this.config.config.collectionAddress,
|
|
559
|
+
recipientAddress: this.getAccountAddress(),
|
|
560
|
+
enableMainCurrencyPayment: true,
|
|
561
|
+
enableSwapPayments: !!checkoutOptions.options?.swap?.includes(
|
|
562
|
+
TransactionSwapProvider.zerox,
|
|
563
|
+
),
|
|
564
|
+
creditCardProviders: checkoutOptions?.options.nftCheckout || [],
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
this.logger.debug('Opening payment modal', paymentModalProps);
|
|
568
|
+
await this.openPaymentModalWithPromise(paymentModalProps);
|
|
569
|
+
} catch (error) {
|
|
570
|
+
if (error instanceof TransactionError) {
|
|
571
|
+
throw error;
|
|
572
|
+
}
|
|
573
|
+
throw new PaymentModalTransactionError(step.id, error as Error);
|
|
574
|
+
}
|
|
575
|
+
} catch (error) {
|
|
576
|
+
if (error instanceof TransactionError) {
|
|
577
|
+
throw error;
|
|
578
|
+
}
|
|
579
|
+
throw new StepExecutionError(step.id, error as Error);
|
|
580
|
+
}
|
|
500
581
|
}
|
|
501
582
|
|
|
502
583
|
private async executeStep({
|
|
@@ -506,43 +587,49 @@ export class TransactionMachine {
|
|
|
506
587
|
step: Step;
|
|
507
588
|
props: TransactionInput['props'];
|
|
508
589
|
}) {
|
|
509
|
-
debug('Executing step', { stepId: step.id });
|
|
510
|
-
if (!step.to && !step.signature) {
|
|
511
|
-
throw new Error('Invalid step data');
|
|
512
|
-
}
|
|
513
|
-
|
|
514
590
|
try {
|
|
591
|
+
this.logger.debug('Executing step', { stepId: step.id });
|
|
592
|
+
|
|
593
|
+
if (!step.to && !step.signature) {
|
|
594
|
+
throw new MissingStepDataError();
|
|
595
|
+
}
|
|
596
|
+
|
|
515
597
|
await this.switchChain();
|
|
598
|
+
|
|
516
599
|
if (step.id === StepType.buy) {
|
|
517
600
|
await this.executeBuyStep({ step, props: props as BuyInput });
|
|
518
|
-
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (step.signature) {
|
|
519
605
|
await this.executeSignature(step);
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const hash = await this.executeTransaction(step);
|
|
610
|
+
|
|
611
|
+
if (step.id !== StepType.tokenApproval) {
|
|
526
612
|
this.config.onSuccess?.(hash);
|
|
527
|
-
return { hash };
|
|
528
613
|
}
|
|
614
|
+
|
|
615
|
+
return { hash };
|
|
529
616
|
} catch (error) {
|
|
530
|
-
|
|
531
|
-
|
|
617
|
+
if (error instanceof TransactionError) {
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
620
|
+
throw new StepExecutionError(step.id, error as Error);
|
|
532
621
|
}
|
|
533
622
|
}
|
|
534
623
|
|
|
535
|
-
async getTransactionSteps(
|
|
536
|
-
|
|
537
|
-
): Promise<TransactionSteps> {
|
|
538
|
-
debug('Getting transaction steps', props);
|
|
624
|
+
async getTransactionSteps(props: Input): Promise<TransactionSteps> {
|
|
625
|
+
this.logger.debug('Getting transaction steps', props);
|
|
539
626
|
// Return memoized value if props and state haven't changed
|
|
540
627
|
if (
|
|
541
628
|
this.memoizedSteps &&
|
|
542
629
|
this.lastProps &&
|
|
543
630
|
JSON.stringify(props) === JSON.stringify(this.lastProps)
|
|
544
631
|
) {
|
|
545
|
-
debug('Returning memoized steps');
|
|
632
|
+
this.logger.debug('Returning memoized steps');
|
|
546
633
|
return this.memoizedSteps;
|
|
547
634
|
}
|
|
548
635
|
|
|
@@ -554,15 +641,15 @@ export class TransactionMachine {
|
|
|
554
641
|
// Extract execution step, it should always be the last step
|
|
555
642
|
const executionStep = steps.pop();
|
|
556
643
|
if (!executionStep) {
|
|
557
|
-
throw new
|
|
644
|
+
throw new NoStepsFoundError();
|
|
558
645
|
}
|
|
559
646
|
if (executionStep.id === StepType.tokenApproval) {
|
|
560
|
-
throw new
|
|
647
|
+
throw new NoExecutionStepError();
|
|
561
648
|
}
|
|
562
649
|
const approvalStep = steps.pop();
|
|
563
650
|
|
|
564
651
|
if (steps.length > 0) {
|
|
565
|
-
throw new
|
|
652
|
+
throw new UnexpectedStepsError();
|
|
566
653
|
}
|
|
567
654
|
|
|
568
655
|
this.lastProps = props;
|
|
@@ -586,7 +673,7 @@ export class TransactionMachine {
|
|
|
586
673
|
},
|
|
587
674
|
} as const;
|
|
588
675
|
|
|
589
|
-
debug('Generated new transaction steps', this.memoizedSteps);
|
|
676
|
+
this.logger.debug('Generated new transaction steps', this.memoizedSteps);
|
|
590
677
|
return this.memoizedSteps;
|
|
591
678
|
}
|
|
592
679
|
}
|