@manifoldxyz/client-sdk 0.2.1-beta.4 → 0.3.0-beta.0
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/README.md +103 -15
- package/dist/{ccip-BG_QuMqH.cjs → ccip-BfMU2f4y.cjs} +4 -105
- package/dist/ccip-BfMU2f4y.cjs.map +1 -0
- package/dist/{ccip-qvYLbkYB.js → ccip-Bv7RkEtW.js} +2 -103
- package/dist/ccip-Bv7RkEtW.js.map +1 -0
- package/dist/{index-DqapYPnx.js → index-Bv8kDpD2.js} +16202 -8516
- package/dist/index-Bv8kDpD2.js.map +1 -0
- package/dist/{index-DW4Czdi9.cjs → index-Dg7f7bCR.cjs} +16186 -8500
- package/dist/index-Dg7f7bCR.cjs.map +1 -0
- package/dist/index.cjs +7 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +494 -108
- package/dist/index.mjs +18 -12
- package/package.json +7 -3
- package/dist/ccip-BG_QuMqH.cjs.map +0 -1
- package/dist/ccip-qvYLbkYB.js.map +0 -1
- package/dist/index-DW4Czdi9.cjs.map +0 -1
- package/dist/index-DqapYPnx.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,9 +8,8 @@ Head to [studio.manifold.xyz](https://studio.manifold.xyz/) to launch your produ
|
|
|
8
8
|
|
|
9
9
|
## ✨ Features
|
|
10
10
|
|
|
11
|
-
- **No API keys required** - Works out of the box
|
|
12
11
|
- **TypeScript first** - Full type safety and IntelliSense
|
|
13
|
-
- **Wallet agnostic** - Works with ethers and viem
|
|
12
|
+
- **Wallet agnostic** - Works with ethers v5 and viem
|
|
14
13
|
- **Support for multiple product types**:
|
|
15
14
|
- Edition
|
|
16
15
|
- Blind Mint
|
|
@@ -21,6 +20,7 @@ Head to [studio.manifold.xyz](https://studio.manifold.xyz/) to launch your produ
|
|
|
21
20
|
- Transaction preparation
|
|
22
21
|
- Cross-chain support (coming soon)
|
|
23
22
|
- Error handling
|
|
23
|
+
- **Built-in provider fallbacks** - Automatic failover between multiple RPC endpoints
|
|
24
24
|
|
|
25
25
|
## 📦 Installation
|
|
26
26
|
|
|
@@ -33,14 +33,24 @@ npm install @manifoldxyz/client-sdk
|
|
|
33
33
|
### 1. Import and Initialize
|
|
34
34
|
|
|
35
35
|
```typescript
|
|
36
|
-
import { createClient } from '@manifoldxyz/client-sdk';
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
import { createClient, createPublicProviderWagmi } from '@manifoldxyz/client-sdk';
|
|
37
|
+
import { createConfig, http } from '@wagmi/core';
|
|
38
|
+
import { mainnet, base } from '@wagmi/core/chains';
|
|
39
|
+
|
|
40
|
+
// Create Wagmi config
|
|
41
|
+
const config = createConfig({
|
|
42
|
+
chains: [mainnet, base],
|
|
43
|
+
transports: {
|
|
44
|
+
[mainnet.id]: http(),
|
|
45
|
+
[base.id]: http(),
|
|
42
46
|
},
|
|
43
47
|
});
|
|
48
|
+
|
|
49
|
+
// Create public provider
|
|
50
|
+
const publicProvider = createPublicProviderWagmi({ config });
|
|
51
|
+
|
|
52
|
+
// Initialize the SDK client
|
|
53
|
+
const client = createClient({ publicProvider });
|
|
44
54
|
```
|
|
45
55
|
|
|
46
56
|
### 2. Get Product Data
|
|
@@ -76,8 +86,23 @@ console.log(`Total cost: ${preparedPurchase.cost.total.formatted}`);
|
|
|
76
86
|
### 4. Execute Purchase
|
|
77
87
|
|
|
78
88
|
```typescript
|
|
89
|
+
// Using viem
|
|
90
|
+
import { createAccountViem } from '@manifoldxyz/client-sdk';
|
|
91
|
+
import { createWalletClient, custom } from 'viem';
|
|
92
|
+
import { mainnet } from 'viem/chains';
|
|
93
|
+
|
|
94
|
+
const walletClient = createWalletClient({
|
|
95
|
+
chain: mainnet,
|
|
96
|
+
transport: custom(window.ethereum),
|
|
97
|
+
});
|
|
98
|
+
const account = createAccountViem({ walletClient });
|
|
99
|
+
|
|
100
|
+
// Or using ethers v5
|
|
101
|
+
import { createAccountEthers5 } from '@manifoldxyz/client-sdk';
|
|
102
|
+
const account = createAccountEthers5({ signer });
|
|
103
|
+
|
|
79
104
|
const order = await product.purchase({
|
|
80
|
-
account
|
|
105
|
+
account,
|
|
81
106
|
preparedPurchase,
|
|
82
107
|
});
|
|
83
108
|
|
|
@@ -88,22 +113,40 @@ console.log(order.receipts[0].txHash, order.status);
|
|
|
88
113
|
|
|
89
114
|
### Client Creation
|
|
90
115
|
|
|
91
|
-
#### `createClient(config
|
|
116
|
+
#### `createClient(config)`
|
|
92
117
|
|
|
93
118
|
Creates a new SDK client instance.
|
|
94
119
|
|
|
95
120
|
**Parameters:**
|
|
96
121
|
|
|
97
|
-
- `
|
|
122
|
+
- `config` (object, required): Configuration options
|
|
123
|
+
- `publicProvider` (IPublicProvider, required): Provider for blockchain interactions
|
|
124
|
+
- `debug` (boolean, optional): Enable debug logging
|
|
98
125
|
|
|
99
126
|
**Example:**
|
|
100
127
|
|
|
101
128
|
```typescript
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
129
|
+
import { createClient, createPublicProviderWagmi } from '@manifoldxyz/client-sdk';
|
|
130
|
+
import { createConfig, http } from '@wagmi/core';
|
|
131
|
+
import { mainnet, base } from '@wagmi/core/chains';
|
|
132
|
+
|
|
133
|
+
// Setup Wagmi config
|
|
134
|
+
const config = createConfig({
|
|
135
|
+
chains: [mainnet, base],
|
|
136
|
+
transports: {
|
|
137
|
+
[mainnet.id]: http(),
|
|
138
|
+
[base.id]: http(),
|
|
105
139
|
},
|
|
106
140
|
});
|
|
141
|
+
|
|
142
|
+
// Create public provider
|
|
143
|
+
const publicProvider = createPublicProviderWagmi({ config });
|
|
144
|
+
|
|
145
|
+
// Create client
|
|
146
|
+
const client = createClient({ publicProvider });
|
|
147
|
+
|
|
148
|
+
// With debug logging
|
|
149
|
+
const client = createClient({ publicProvider, debug: true });
|
|
107
150
|
```
|
|
108
151
|
|
|
109
152
|
### Client Methods
|
|
@@ -175,7 +218,7 @@ Executes the purchase transaction(s).
|
|
|
175
218
|
|
|
176
219
|
**Parameters:**
|
|
177
220
|
|
|
178
|
-
- `account`: Wallet account
|
|
221
|
+
- `account`: Wallet account adapter (see Wallet Adapters section)
|
|
179
222
|
- `preparedPurchase`: Result from `preparePurchase()`
|
|
180
223
|
|
|
181
224
|
**Returns:** `Order` with transaction receipts and status
|
|
@@ -207,6 +250,51 @@ interface BlindMintProduct {
|
|
|
207
250
|
}
|
|
208
251
|
```
|
|
209
252
|
|
|
253
|
+
## 🔌 Wallet Adapters
|
|
254
|
+
|
|
255
|
+
The SDK supports multiple wallet libraries through adapters:
|
|
256
|
+
|
|
257
|
+
### Viem
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { createWalletClient, custom, http } from 'viem';
|
|
261
|
+
import { mainnet } from 'viem/chains';
|
|
262
|
+
import { createAccountViem } from '@manifoldxyz/client-sdk';
|
|
263
|
+
|
|
264
|
+
// Using browser wallet (MetaMask, etc.)
|
|
265
|
+
const walletClient = createWalletClient({
|
|
266
|
+
chain: mainnet,
|
|
267
|
+
transport: custom(window.ethereum),
|
|
268
|
+
});
|
|
269
|
+
const account = createAccountViem({ walletClient });
|
|
270
|
+
|
|
271
|
+
// Using private key
|
|
272
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
273
|
+
const viemAccount = privateKeyToAccount('0x...');
|
|
274
|
+
const walletClient = createWalletClient({
|
|
275
|
+
account: viemAccount,
|
|
276
|
+
chain: mainnet,
|
|
277
|
+
transport: http(),
|
|
278
|
+
});
|
|
279
|
+
const account = createAccountViem({ walletClient });
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Ethers v5
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { ethers } from 'ethers';
|
|
286
|
+
import { createAccountEthers5 } from '@manifoldxyz/client-sdk';
|
|
287
|
+
|
|
288
|
+
// Using MetaMask or other browser wallet
|
|
289
|
+
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
|
290
|
+
const signer = provider.getSigner();
|
|
291
|
+
const account = createAccountEthers5({ signer });
|
|
292
|
+
|
|
293
|
+
// Using a private key
|
|
294
|
+
const wallet = new ethers.Wallet(privateKey, provider);
|
|
295
|
+
const account = createAccountEthers5({ signer: wallet });
|
|
296
|
+
```
|
|
297
|
+
|
|
210
298
|
## 🧪 Testing
|
|
211
299
|
|
|
212
300
|
Run the playground to test the SDK:
|
|
@@ -1,107 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const index = require("./index-
|
|
4
|
-
function decodeFunctionData(parameters) {
|
|
5
|
-
const { abi, data } = parameters;
|
|
6
|
-
const signature = index.slice(data, 0, 4);
|
|
7
|
-
const description = abi.find((x) => x.type === "function" && signature === index.toFunctionSelector(index.formatAbiItem(x)));
|
|
8
|
-
if (!description)
|
|
9
|
-
throw new index.AbiFunctionSignatureNotFoundError(signature, {
|
|
10
|
-
docsPath: "/docs/contract/decodeFunctionData"
|
|
11
|
-
});
|
|
12
|
-
return {
|
|
13
|
-
functionName: description.name,
|
|
14
|
-
args: "inputs" in description && description.inputs && description.inputs.length > 0 ? index.decodeAbiParameters(description.inputs, index.slice(data, 4)) : void 0
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
const docsPath$1 = "/docs/contract/encodeErrorResult";
|
|
18
|
-
function encodeErrorResult(parameters) {
|
|
19
|
-
const { abi, errorName, args } = parameters;
|
|
20
|
-
let abiItem = abi[0];
|
|
21
|
-
if (errorName) {
|
|
22
|
-
const item = index.getAbiItem({ abi, args, name: errorName });
|
|
23
|
-
if (!item)
|
|
24
|
-
throw new index.AbiErrorNotFoundError(errorName, { docsPath: docsPath$1 });
|
|
25
|
-
abiItem = item;
|
|
26
|
-
}
|
|
27
|
-
if (abiItem.type !== "error")
|
|
28
|
-
throw new index.AbiErrorNotFoundError(void 0, { docsPath: docsPath$1 });
|
|
29
|
-
const definition = index.formatAbiItem(abiItem);
|
|
30
|
-
const signature = index.toFunctionSelector(definition);
|
|
31
|
-
let data = "0x";
|
|
32
|
-
if (args && args.length > 0) {
|
|
33
|
-
if (!abiItem.inputs)
|
|
34
|
-
throw new index.AbiErrorInputsNotFoundError(abiItem.name, { docsPath: docsPath$1 });
|
|
35
|
-
data = index.encodeAbiParameters(abiItem.inputs, args);
|
|
36
|
-
}
|
|
37
|
-
return index.concatHex([signature, data]);
|
|
38
|
-
}
|
|
39
|
-
const docsPath = "/docs/contract/encodeFunctionResult";
|
|
40
|
-
function encodeFunctionResult(parameters) {
|
|
41
|
-
const { abi, functionName, result } = parameters;
|
|
42
|
-
let abiItem = abi[0];
|
|
43
|
-
if (functionName) {
|
|
44
|
-
const item = index.getAbiItem({ abi, name: functionName });
|
|
45
|
-
if (!item)
|
|
46
|
-
throw new index.AbiFunctionNotFoundError(functionName, { docsPath });
|
|
47
|
-
abiItem = item;
|
|
48
|
-
}
|
|
49
|
-
if (abiItem.type !== "function")
|
|
50
|
-
throw new index.AbiFunctionNotFoundError(void 0, { docsPath });
|
|
51
|
-
if (!abiItem.outputs)
|
|
52
|
-
throw new index.AbiFunctionOutputsNotFoundError(abiItem.name, { docsPath });
|
|
53
|
-
const values = (() => {
|
|
54
|
-
if (abiItem.outputs.length === 0)
|
|
55
|
-
return [];
|
|
56
|
-
if (abiItem.outputs.length === 1)
|
|
57
|
-
return [result];
|
|
58
|
-
if (Array.isArray(result))
|
|
59
|
-
return result;
|
|
60
|
-
throw new index.InvalidArrayError(result);
|
|
61
|
-
})();
|
|
62
|
-
return index.encodeAbiParameters(abiItem.outputs, values);
|
|
63
|
-
}
|
|
64
|
-
const localBatchGatewayUrl = "x-batch-gateway:true";
|
|
65
|
-
async function localBatchGatewayRequest(parameters) {
|
|
66
|
-
const { data, ccipRequest: ccipRequest2 } = parameters;
|
|
67
|
-
const { args: [queries] } = decodeFunctionData({ abi: index.batchGatewayAbi, data });
|
|
68
|
-
const failures = [];
|
|
69
|
-
const responses = [];
|
|
70
|
-
await Promise.all(queries.map(async (query, i) => {
|
|
71
|
-
try {
|
|
72
|
-
responses[i] = query.urls.includes(localBatchGatewayUrl) ? await localBatchGatewayRequest({ data: query.data, ccipRequest: ccipRequest2 }) : await ccipRequest2(query);
|
|
73
|
-
failures[i] = false;
|
|
74
|
-
} catch (err) {
|
|
75
|
-
failures[i] = true;
|
|
76
|
-
responses[i] = encodeError(err);
|
|
77
|
-
}
|
|
78
|
-
}));
|
|
79
|
-
return encodeFunctionResult({
|
|
80
|
-
abi: index.batchGatewayAbi,
|
|
81
|
-
functionName: "query",
|
|
82
|
-
result: [failures, responses]
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
function encodeError(error) {
|
|
86
|
-
if (error.name === "HttpRequestError" && error.status)
|
|
87
|
-
return encodeErrorResult({
|
|
88
|
-
abi: index.batchGatewayAbi,
|
|
89
|
-
errorName: "HttpError",
|
|
90
|
-
args: [error.status, error.shortMessage]
|
|
91
|
-
});
|
|
92
|
-
return encodeErrorResult({
|
|
93
|
-
abi: [index.solidityError],
|
|
94
|
-
errorName: "Error",
|
|
95
|
-
args: ["shortMessage" in error ? error.shortMessage : error.message]
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
function isAddressEqual(a, b) {
|
|
99
|
-
if (!index.isAddress(a, { strict: false }))
|
|
100
|
-
throw new index.InvalidAddressError({ address: a });
|
|
101
|
-
if (!index.isAddress(b, { strict: false }))
|
|
102
|
-
throw new index.InvalidAddressError({ address: b });
|
|
103
|
-
return a.toLowerCase() === b.toLowerCase();
|
|
104
|
-
}
|
|
3
|
+
const index = require("./index-Dg7f7bCR.cjs");
|
|
105
4
|
class OffchainLookupError extends index.BaseError {
|
|
106
5
|
constructor({ callbackSelector, cause, data, extraData, sender, urls }) {
|
|
107
6
|
super(cause.shortMessage || "An error occurred while fetching for an offchain result.", {
|
|
@@ -181,9 +80,9 @@ async function offchainLookup(client, { blockNumber, blockTag, data, to }) {
|
|
|
181
80
|
const { ccipRead } = client;
|
|
182
81
|
const ccipRequest_ = ccipRead && typeof ccipRead?.request === "function" ? ccipRead.request : ccipRequest;
|
|
183
82
|
try {
|
|
184
|
-
if (!isAddressEqual(to, sender))
|
|
83
|
+
if (!index.isAddressEqual(to, sender))
|
|
185
84
|
throw new OffchainLookupSenderMismatchError({ sender, to });
|
|
186
|
-
const result = urls.includes(localBatchGatewayUrl) ? await localBatchGatewayRequest({
|
|
85
|
+
const result = urls.includes(index.localBatchGatewayUrl) ? await index.localBatchGatewayRequest({
|
|
187
86
|
data: callData,
|
|
188
87
|
ccipRequest: ccipRequest_
|
|
189
88
|
}) : await ccipRequest_({ data: callData, sender, urls });
|
|
@@ -259,4 +158,4 @@ exports.ccipRequest = ccipRequest;
|
|
|
259
158
|
exports.offchainLookup = offchainLookup;
|
|
260
159
|
exports.offchainLookupAbiItem = offchainLookupAbiItem;
|
|
261
160
|
exports.offchainLookupSignature = offchainLookupSignature;
|
|
262
|
-
//# sourceMappingURL=ccip-
|
|
161
|
+
//# sourceMappingURL=ccip-BfMU2f4y.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ccip-BfMU2f4y.cjs","sources":["../../../node_modules/.pnpm/viem@2.38.5_bufferutil@4.0.9_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.1.12/node_modules/viem/_esm/errors/ccip.js","../../../node_modules/.pnpm/viem@2.38.5_bufferutil@4.0.9_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.1.12/node_modules/viem/_esm/utils/ccip.js"],"sourcesContent":["import { stringify } from '../utils/stringify.js';\nimport { BaseError } from './base.js';\nimport { getUrl } from './utils.js';\nexport class OffchainLookupError extends BaseError {\n constructor({ callbackSelector, cause, data, extraData, sender, urls, }) {\n super(cause.shortMessage ||\n 'An error occurred while fetching for an offchain result.', {\n cause,\n metaMessages: [\n ...(cause.metaMessages || []),\n cause.metaMessages?.length ? '' : [],\n 'Offchain Gateway Call:',\n urls && [\n ' Gateway URL(s):',\n ...urls.map((url) => ` ${getUrl(url)}`),\n ],\n ` Sender: ${sender}`,\n ` Data: ${data}`,\n ` Callback selector: ${callbackSelector}`,\n ` Extra data: ${extraData}`,\n ].flat(),\n name: 'OffchainLookupError',\n });\n }\n}\nexport class OffchainLookupResponseMalformedError extends BaseError {\n constructor({ result, url }) {\n super('Offchain gateway response is malformed. Response data must be a hex value.', {\n metaMessages: [\n `Gateway URL: ${getUrl(url)}`,\n `Response: ${stringify(result)}`,\n ],\n name: 'OffchainLookupResponseMalformedError',\n });\n }\n}\nexport class OffchainLookupSenderMismatchError extends BaseError {\n constructor({ sender, to }) {\n super('Reverted sender address does not match target contract address (`to`).', {\n metaMessages: [\n `Contract address: ${to}`,\n `OffchainLookup sender address: ${sender}`,\n ],\n name: 'OffchainLookupSenderMismatchError',\n });\n }\n}\n//# sourceMappingURL=ccip.js.map","import { call } from '../actions/public/call.js';\nimport { OffchainLookupError, OffchainLookupResponseMalformedError, OffchainLookupSenderMismatchError, } from '../errors/ccip.js';\nimport { HttpRequestError, } from '../errors/request.js';\nimport { decodeErrorResult } from './abi/decodeErrorResult.js';\nimport { encodeAbiParameters } from './abi/encodeAbiParameters.js';\nimport { isAddressEqual } from './address/isAddressEqual.js';\nimport { concat } from './data/concat.js';\nimport { isHex } from './data/isHex.js';\nimport { localBatchGatewayRequest, localBatchGatewayUrl, } from './ens/localBatchGatewayRequest.js';\nimport { stringify } from './stringify.js';\nexport const offchainLookupSignature = '0x556f1830';\nexport const offchainLookupAbiItem = {\n name: 'OffchainLookup',\n type: 'error',\n inputs: [\n {\n name: 'sender',\n type: 'address',\n },\n {\n name: 'urls',\n type: 'string[]',\n },\n {\n name: 'callData',\n type: 'bytes',\n },\n {\n name: 'callbackFunction',\n type: 'bytes4',\n },\n {\n name: 'extraData',\n type: 'bytes',\n },\n ],\n};\nexport async function offchainLookup(client, { blockNumber, blockTag, data, to, }) {\n const { args } = decodeErrorResult({\n data,\n abi: [offchainLookupAbiItem],\n });\n const [sender, urls, callData, callbackSelector, extraData] = args;\n const { ccipRead } = client;\n const ccipRequest_ = ccipRead && typeof ccipRead?.request === 'function'\n ? ccipRead.request\n : ccipRequest;\n try {\n if (!isAddressEqual(to, sender))\n throw new OffchainLookupSenderMismatchError({ sender, to });\n const result = urls.includes(localBatchGatewayUrl)\n ? await localBatchGatewayRequest({\n data: callData,\n ccipRequest: ccipRequest_,\n })\n : await ccipRequest_({ data: callData, sender, urls });\n const { data: data_ } = await call(client, {\n blockNumber,\n blockTag,\n data: concat([\n callbackSelector,\n encodeAbiParameters([{ type: 'bytes' }, { type: 'bytes' }], [result, extraData]),\n ]),\n to,\n });\n return data_;\n }\n catch (err) {\n throw new OffchainLookupError({\n callbackSelector,\n cause: err,\n data,\n extraData,\n sender,\n urls,\n });\n }\n}\nexport async function ccipRequest({ data, sender, urls, }) {\n let error = new Error('An unknown error occurred.');\n for (let i = 0; i < urls.length; i++) {\n const url = urls[i];\n const method = url.includes('{data}') ? 'GET' : 'POST';\n const body = method === 'POST' ? { data, sender } : undefined;\n const headers = method === 'POST' ? { 'Content-Type': 'application/json' } : {};\n try {\n const response = await fetch(url.replace('{sender}', sender.toLowerCase()).replace('{data}', data), {\n body: JSON.stringify(body),\n headers,\n method,\n });\n let result;\n if (response.headers.get('Content-Type')?.startsWith('application/json')) {\n result = (await response.json()).data;\n }\n else {\n result = (await response.text());\n }\n if (!response.ok) {\n error = new HttpRequestError({\n body,\n details: result?.error\n ? stringify(result.error)\n : response.statusText,\n headers: response.headers,\n status: response.status,\n url,\n });\n continue;\n }\n if (!isHex(result)) {\n error = new OffchainLookupResponseMalformedError({\n result,\n url,\n });\n continue;\n }\n return result;\n }\n catch (err) {\n error = new HttpRequestError({\n body,\n details: err.message,\n url,\n });\n }\n }\n throw error;\n}\n//# sourceMappingURL=ccip.js.map"],"names":["BaseError","getUrl","stringify","decodeErrorResult","isAddressEqual","localBatchGatewayUrl","localBatchGatewayRequest","call","concat","encodeAbiParameters","HttpRequestError","isHex"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1,105 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
function decodeFunctionData(parameters) {
|
|
3
|
-
const { abi, data } = parameters;
|
|
4
|
-
const signature = slice(data, 0, 4);
|
|
5
|
-
const description = abi.find((x) => x.type === "function" && signature === toFunctionSelector(formatAbiItem(x)));
|
|
6
|
-
if (!description)
|
|
7
|
-
throw new AbiFunctionSignatureNotFoundError(signature, {
|
|
8
|
-
docsPath: "/docs/contract/decodeFunctionData"
|
|
9
|
-
});
|
|
10
|
-
return {
|
|
11
|
-
functionName: description.name,
|
|
12
|
-
args: "inputs" in description && description.inputs && description.inputs.length > 0 ? decodeAbiParameters(description.inputs, slice(data, 4)) : void 0
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
const docsPath$1 = "/docs/contract/encodeErrorResult";
|
|
16
|
-
function encodeErrorResult(parameters) {
|
|
17
|
-
const { abi, errorName, args } = parameters;
|
|
18
|
-
let abiItem = abi[0];
|
|
19
|
-
if (errorName) {
|
|
20
|
-
const item = getAbiItem({ abi, args, name: errorName });
|
|
21
|
-
if (!item)
|
|
22
|
-
throw new AbiErrorNotFoundError(errorName, { docsPath: docsPath$1 });
|
|
23
|
-
abiItem = item;
|
|
24
|
-
}
|
|
25
|
-
if (abiItem.type !== "error")
|
|
26
|
-
throw new AbiErrorNotFoundError(void 0, { docsPath: docsPath$1 });
|
|
27
|
-
const definition = formatAbiItem(abiItem);
|
|
28
|
-
const signature = toFunctionSelector(definition);
|
|
29
|
-
let data = "0x";
|
|
30
|
-
if (args && args.length > 0) {
|
|
31
|
-
if (!abiItem.inputs)
|
|
32
|
-
throw new AbiErrorInputsNotFoundError(abiItem.name, { docsPath: docsPath$1 });
|
|
33
|
-
data = encodeAbiParameters(abiItem.inputs, args);
|
|
34
|
-
}
|
|
35
|
-
return concatHex([signature, data]);
|
|
36
|
-
}
|
|
37
|
-
const docsPath = "/docs/contract/encodeFunctionResult";
|
|
38
|
-
function encodeFunctionResult(parameters) {
|
|
39
|
-
const { abi, functionName, result } = parameters;
|
|
40
|
-
let abiItem = abi[0];
|
|
41
|
-
if (functionName) {
|
|
42
|
-
const item = getAbiItem({ abi, name: functionName });
|
|
43
|
-
if (!item)
|
|
44
|
-
throw new AbiFunctionNotFoundError(functionName, { docsPath });
|
|
45
|
-
abiItem = item;
|
|
46
|
-
}
|
|
47
|
-
if (abiItem.type !== "function")
|
|
48
|
-
throw new AbiFunctionNotFoundError(void 0, { docsPath });
|
|
49
|
-
if (!abiItem.outputs)
|
|
50
|
-
throw new AbiFunctionOutputsNotFoundError(abiItem.name, { docsPath });
|
|
51
|
-
const values = (() => {
|
|
52
|
-
if (abiItem.outputs.length === 0)
|
|
53
|
-
return [];
|
|
54
|
-
if (abiItem.outputs.length === 1)
|
|
55
|
-
return [result];
|
|
56
|
-
if (Array.isArray(result))
|
|
57
|
-
return result;
|
|
58
|
-
throw new InvalidArrayError(result);
|
|
59
|
-
})();
|
|
60
|
-
return encodeAbiParameters(abiItem.outputs, values);
|
|
61
|
-
}
|
|
62
|
-
const localBatchGatewayUrl = "x-batch-gateway:true";
|
|
63
|
-
async function localBatchGatewayRequest(parameters) {
|
|
64
|
-
const { data, ccipRequest: ccipRequest2 } = parameters;
|
|
65
|
-
const { args: [queries] } = decodeFunctionData({ abi: batchGatewayAbi, data });
|
|
66
|
-
const failures = [];
|
|
67
|
-
const responses = [];
|
|
68
|
-
await Promise.all(queries.map(async (query, i) => {
|
|
69
|
-
try {
|
|
70
|
-
responses[i] = query.urls.includes(localBatchGatewayUrl) ? await localBatchGatewayRequest({ data: query.data, ccipRequest: ccipRequest2 }) : await ccipRequest2(query);
|
|
71
|
-
failures[i] = false;
|
|
72
|
-
} catch (err) {
|
|
73
|
-
failures[i] = true;
|
|
74
|
-
responses[i] = encodeError(err);
|
|
75
|
-
}
|
|
76
|
-
}));
|
|
77
|
-
return encodeFunctionResult({
|
|
78
|
-
abi: batchGatewayAbi,
|
|
79
|
-
functionName: "query",
|
|
80
|
-
result: [failures, responses]
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
function encodeError(error) {
|
|
84
|
-
if (error.name === "HttpRequestError" && error.status)
|
|
85
|
-
return encodeErrorResult({
|
|
86
|
-
abi: batchGatewayAbi,
|
|
87
|
-
errorName: "HttpError",
|
|
88
|
-
args: [error.status, error.shortMessage]
|
|
89
|
-
});
|
|
90
|
-
return encodeErrorResult({
|
|
91
|
-
abi: [solidityError],
|
|
92
|
-
errorName: "Error",
|
|
93
|
-
args: ["shortMessage" in error ? error.shortMessage : error.message]
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function isAddressEqual(a, b) {
|
|
97
|
-
if (!isAddress(a, { strict: false }))
|
|
98
|
-
throw new InvalidAddressError({ address: a });
|
|
99
|
-
if (!isAddress(b, { strict: false }))
|
|
100
|
-
throw new InvalidAddressError({ address: b });
|
|
101
|
-
return a.toLowerCase() === b.toLowerCase();
|
|
102
|
-
}
|
|
1
|
+
import { B as BaseError, g as getUrl, s as stringify, d as decodeErrorResult, i as isAddressEqual, l as localBatchGatewayUrl, a as localBatchGatewayRequest, c as call, b as concat, e as encodeAbiParameters, H as HttpRequestError, f as isHex } from "./index-Bv8kDpD2.js";
|
|
103
2
|
class OffchainLookupError extends BaseError {
|
|
104
3
|
constructor({ callbackSelector, cause, data, extraData, sender, urls }) {
|
|
105
4
|
super(cause.shortMessage || "An error occurred while fetching for an offchain result.", {
|
|
@@ -259,4 +158,4 @@ export {
|
|
|
259
158
|
offchainLookupAbiItem,
|
|
260
159
|
offchainLookupSignature
|
|
261
160
|
};
|
|
262
|
-
//# sourceMappingURL=ccip-
|
|
161
|
+
//# sourceMappingURL=ccip-Bv7RkEtW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ccip-Bv7RkEtW.js","sources":["../../../node_modules/.pnpm/viem@2.38.5_bufferutil@4.0.9_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.1.12/node_modules/viem/_esm/errors/ccip.js","../../../node_modules/.pnpm/viem@2.38.5_bufferutil@4.0.9_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.1.12/node_modules/viem/_esm/utils/ccip.js"],"sourcesContent":["import { stringify } from '../utils/stringify.js';\nimport { BaseError } from './base.js';\nimport { getUrl } from './utils.js';\nexport class OffchainLookupError extends BaseError {\n constructor({ callbackSelector, cause, data, extraData, sender, urls, }) {\n super(cause.shortMessage ||\n 'An error occurred while fetching for an offchain result.', {\n cause,\n metaMessages: [\n ...(cause.metaMessages || []),\n cause.metaMessages?.length ? '' : [],\n 'Offchain Gateway Call:',\n urls && [\n ' Gateway URL(s):',\n ...urls.map((url) => ` ${getUrl(url)}`),\n ],\n ` Sender: ${sender}`,\n ` Data: ${data}`,\n ` Callback selector: ${callbackSelector}`,\n ` Extra data: ${extraData}`,\n ].flat(),\n name: 'OffchainLookupError',\n });\n }\n}\nexport class OffchainLookupResponseMalformedError extends BaseError {\n constructor({ result, url }) {\n super('Offchain gateway response is malformed. Response data must be a hex value.', {\n metaMessages: [\n `Gateway URL: ${getUrl(url)}`,\n `Response: ${stringify(result)}`,\n ],\n name: 'OffchainLookupResponseMalformedError',\n });\n }\n}\nexport class OffchainLookupSenderMismatchError extends BaseError {\n constructor({ sender, to }) {\n super('Reverted sender address does not match target contract address (`to`).', {\n metaMessages: [\n `Contract address: ${to}`,\n `OffchainLookup sender address: ${sender}`,\n ],\n name: 'OffchainLookupSenderMismatchError',\n });\n }\n}\n//# sourceMappingURL=ccip.js.map","import { call } from '../actions/public/call.js';\nimport { OffchainLookupError, OffchainLookupResponseMalformedError, OffchainLookupSenderMismatchError, } from '../errors/ccip.js';\nimport { HttpRequestError, } from '../errors/request.js';\nimport { decodeErrorResult } from './abi/decodeErrorResult.js';\nimport { encodeAbiParameters } from './abi/encodeAbiParameters.js';\nimport { isAddressEqual } from './address/isAddressEqual.js';\nimport { concat } from './data/concat.js';\nimport { isHex } from './data/isHex.js';\nimport { localBatchGatewayRequest, localBatchGatewayUrl, } from './ens/localBatchGatewayRequest.js';\nimport { stringify } from './stringify.js';\nexport const offchainLookupSignature = '0x556f1830';\nexport const offchainLookupAbiItem = {\n name: 'OffchainLookup',\n type: 'error',\n inputs: [\n {\n name: 'sender',\n type: 'address',\n },\n {\n name: 'urls',\n type: 'string[]',\n },\n {\n name: 'callData',\n type: 'bytes',\n },\n {\n name: 'callbackFunction',\n type: 'bytes4',\n },\n {\n name: 'extraData',\n type: 'bytes',\n },\n ],\n};\nexport async function offchainLookup(client, { blockNumber, blockTag, data, to, }) {\n const { args } = decodeErrorResult({\n data,\n abi: [offchainLookupAbiItem],\n });\n const [sender, urls, callData, callbackSelector, extraData] = args;\n const { ccipRead } = client;\n const ccipRequest_ = ccipRead && typeof ccipRead?.request === 'function'\n ? ccipRead.request\n : ccipRequest;\n try {\n if (!isAddressEqual(to, sender))\n throw new OffchainLookupSenderMismatchError({ sender, to });\n const result = urls.includes(localBatchGatewayUrl)\n ? await localBatchGatewayRequest({\n data: callData,\n ccipRequest: ccipRequest_,\n })\n : await ccipRequest_({ data: callData, sender, urls });\n const { data: data_ } = await call(client, {\n blockNumber,\n blockTag,\n data: concat([\n callbackSelector,\n encodeAbiParameters([{ type: 'bytes' }, { type: 'bytes' }], [result, extraData]),\n ]),\n to,\n });\n return data_;\n }\n catch (err) {\n throw new OffchainLookupError({\n callbackSelector,\n cause: err,\n data,\n extraData,\n sender,\n urls,\n });\n }\n}\nexport async function ccipRequest({ data, sender, urls, }) {\n let error = new Error('An unknown error occurred.');\n for (let i = 0; i < urls.length; i++) {\n const url = urls[i];\n const method = url.includes('{data}') ? 'GET' : 'POST';\n const body = method === 'POST' ? { data, sender } : undefined;\n const headers = method === 'POST' ? { 'Content-Type': 'application/json' } : {};\n try {\n const response = await fetch(url.replace('{sender}', sender.toLowerCase()).replace('{data}', data), {\n body: JSON.stringify(body),\n headers,\n method,\n });\n let result;\n if (response.headers.get('Content-Type')?.startsWith('application/json')) {\n result = (await response.json()).data;\n }\n else {\n result = (await response.text());\n }\n if (!response.ok) {\n error = new HttpRequestError({\n body,\n details: result?.error\n ? stringify(result.error)\n : response.statusText,\n headers: response.headers,\n status: response.status,\n url,\n });\n continue;\n }\n if (!isHex(result)) {\n error = new OffchainLookupResponseMalformedError({\n result,\n url,\n });\n continue;\n }\n return result;\n }\n catch (err) {\n error = new HttpRequestError({\n body,\n details: err.message,\n url,\n });\n }\n }\n throw error;\n}\n//# sourceMappingURL=ccip.js.map"],"names":[],"mappings":"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","x_google_ignoreList":[0,1]}
|