@0xsequence/relayer 2.3.39 → 3.0.0-beta.10
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/.turbo/turbo-build.log +5 -0
- package/CHANGELOG.md +3926 -0
- package/LICENSE +0 -17
- package/README.md +1 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/preconditions/codec.d.ts +12 -0
- package/dist/preconditions/codec.d.ts.map +1 -0
- package/dist/preconditions/codec.js +125 -0
- package/dist/preconditions/index.d.ts +4 -0
- package/dist/preconditions/index.d.ts.map +1 -0
- package/dist/preconditions/index.js +3 -0
- package/dist/preconditions/selectors.d.ts +7 -0
- package/dist/preconditions/selectors.d.ts.map +1 -0
- package/dist/preconditions/selectors.js +27 -0
- package/dist/preconditions/types.d.ts +70 -0
- package/dist/preconditions/types.d.ts.map +1 -0
- package/dist/preconditions/types.js +203 -0
- package/dist/relayer/index.d.ts +45 -0
- package/dist/relayer/index.d.ts.map +1 -0
- package/dist/relayer/index.js +3 -0
- package/dist/relayer/relayer.d.ts +26 -0
- package/dist/relayer/relayer.d.ts.map +1 -0
- package/dist/relayer/relayer.js +7 -0
- package/dist/relayer/rpc-relayer/index.d.ts +38 -0
- package/dist/relayer/rpc-relayer/index.d.ts.map +1 -0
- package/dist/relayer/rpc-relayer/index.js +375 -0
- package/dist/{declarations/src → relayer}/rpc-relayer/relayer.gen.d.ts +3 -2
- package/dist/relayer/rpc-relayer/relayer.gen.d.ts.map +1 -0
- package/dist/relayer/rpc-relayer/relayer.gen.js +1246 -0
- package/dist/relayer/standard/abi.d.ts +73 -0
- package/dist/relayer/standard/abi.d.ts.map +1 -0
- package/dist/relayer/standard/abi.js +10 -0
- package/dist/relayer/standard/eip6963.d.ts +31 -0
- package/dist/relayer/standard/eip6963.d.ts.map +1 -0
- package/dist/relayer/standard/eip6963.js +51 -0
- package/dist/relayer/standard/index.d.ts +5 -0
- package/dist/relayer/standard/index.d.ts.map +1 -0
- package/dist/relayer/standard/index.js +4 -0
- package/dist/relayer/standard/local.d.ts +60 -0
- package/dist/relayer/standard/local.d.ts.map +1 -0
- package/dist/relayer/standard/local.js +285 -0
- package/dist/relayer/standard/pk-relayer.d.ts +28 -0
- package/dist/relayer/standard/pk-relayer.d.ts.map +1 -0
- package/dist/relayer/standard/pk-relayer.js +112 -0
- package/dist/relayer/standard/sequence.d.ts +27 -0
- package/dist/relayer/standard/sequence.d.ts.map +1 -0
- package/dist/relayer/standard/sequence.js +84 -0
- package/package.json +28 -25
- package/src/index.ts +3 -111
- package/src/preconditions/codec.ts +190 -0
- package/src/preconditions/index.ts +3 -0
- package/src/preconditions/selectors.ts +38 -0
- package/src/preconditions/types.ts +201 -0
- package/src/relayer/index.ts +60 -0
- package/src/relayer/relayer.ts +37 -0
- package/src/relayer/rpc-relayer/index.ts +449 -0
- package/src/{rpc-relayer → relayer/rpc-relayer}/relayer.gen.ts +483 -258
- package/src/relayer/standard/abi.ts +13 -0
- package/src/relayer/standard/eip6963.ts +74 -0
- package/src/relayer/standard/index.ts +4 -0
- package/src/relayer/standard/local.ts +353 -0
- package/src/relayer/standard/pk-relayer.ts +138 -0
- package/src/relayer/standard/sequence.ts +110 -0
- package/test/preconditions/codec.test.ts +531 -0
- package/test/preconditions/preconditions.test.ts +283 -0
- package/test/preconditions/selectors.test.ts +415 -0
- package/test/preconditions/types.test.ts +443 -0
- package/test/relayer/relayer.test.ts +355 -0
- package/tsconfig.json +10 -0
- package/dist/0xsequence-relayer.cjs.d.ts +0 -2
- package/dist/0xsequence-relayer.cjs.dev.js +0 -1865
- package/dist/0xsequence-relayer.cjs.js +0 -7
- package/dist/0xsequence-relayer.cjs.prod.js +0 -1865
- package/dist/0xsequence-relayer.esm.js +0 -1852
- package/dist/declarations/src/index.d.ts +0 -42
- package/dist/declarations/src/local-relayer.d.ts +0 -35
- package/dist/declarations/src/provider-relayer.d.ts +0 -47
- package/dist/declarations/src/rpc-relayer/index.d.ts +0 -72
- package/src/local-relayer.ts +0 -125
- package/src/provider-relayer.ts +0 -284
- package/src/rpc-relayer/index.ts +0 -380
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Relayer as GenRelayer,
|
|
3
|
+
SendMetaTxnReturn as RpcSendMetaTxnReturn,
|
|
4
|
+
MetaTxn as RpcMetaTxn,
|
|
5
|
+
FeeTokenType,
|
|
6
|
+
FeeToken as RpcFeeToken,
|
|
7
|
+
TransactionPrecondition,
|
|
8
|
+
ETHTxnStatus,
|
|
9
|
+
} from './relayer.gen.js'
|
|
10
|
+
import { Address, Hex, Bytes, AbiFunction } from 'ox'
|
|
11
|
+
import { Constants, Payload, Network } from '@0xsequence/wallet-primitives'
|
|
12
|
+
import { FeeOption, FeeQuote, OperationStatus, Relayer } from '../index.js'
|
|
13
|
+
import { decodePrecondition } from '../../preconditions/index.js'
|
|
14
|
+
import {
|
|
15
|
+
erc20BalanceOf,
|
|
16
|
+
erc20Allowance,
|
|
17
|
+
erc721OwnerOf,
|
|
18
|
+
erc721GetApproved,
|
|
19
|
+
erc1155BalanceOf,
|
|
20
|
+
erc1155IsApprovedForAll,
|
|
21
|
+
} from '../standard/abi.js'
|
|
22
|
+
import { PublicClient, createPublicClient, http, Chain } from 'viem'
|
|
23
|
+
import * as chains from 'viem/chains'
|
|
24
|
+
|
|
25
|
+
export type Fetch = (input: RequestInfo, init?: RequestInit) => Promise<Response>
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Convert a Sequence Network to a viem Chain
|
|
29
|
+
*/
|
|
30
|
+
const networkToChain = (network: Network.Network): Chain => {
|
|
31
|
+
return {
|
|
32
|
+
id: network.chainId,
|
|
33
|
+
name: network.title || network.name,
|
|
34
|
+
nativeCurrency: {
|
|
35
|
+
name: network.nativeCurrency.name,
|
|
36
|
+
symbol: network.nativeCurrency.symbol,
|
|
37
|
+
decimals: network.nativeCurrency.decimals,
|
|
38
|
+
},
|
|
39
|
+
rpcUrls: {
|
|
40
|
+
default: {
|
|
41
|
+
http: [network.rpcUrl],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
blockExplorers: network.blockExplorer
|
|
45
|
+
? {
|
|
46
|
+
default: {
|
|
47
|
+
name: network.blockExplorer.name || 'Explorer',
|
|
48
|
+
url: network.blockExplorer.url,
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
: undefined,
|
|
52
|
+
contracts: network.ensAddress
|
|
53
|
+
? {
|
|
54
|
+
ensUniversalResolver: {
|
|
55
|
+
address: network.ensAddress as `0x${string}`,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
: undefined,
|
|
59
|
+
} as Chain
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const getChain = (chainId: number): Chain => {
|
|
63
|
+
// First try to get the chain from Sequence's network configurations
|
|
64
|
+
const sequenceNetwork = Network.getNetworkFromChainId(chainId)
|
|
65
|
+
if (sequenceNetwork) {
|
|
66
|
+
return networkToChain(sequenceNetwork)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Fall back to viem's built-in chains
|
|
70
|
+
const viemChain = Object.values(chains).find((c: any) => typeof c === 'object' && 'id' in c && c.id === chainId)
|
|
71
|
+
if (viemChain) {
|
|
72
|
+
return viemChain as Chain
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw new Error(`Chain with id ${chainId} not found in Sequence networks or viem chains`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export class RpcRelayer implements Relayer {
|
|
79
|
+
public readonly kind: 'relayer' = 'relayer'
|
|
80
|
+
public readonly type = 'rpc'
|
|
81
|
+
public readonly id: string
|
|
82
|
+
public readonly chainId: number
|
|
83
|
+
private client: GenRelayer
|
|
84
|
+
private fetch: Fetch
|
|
85
|
+
private provider: PublicClient
|
|
86
|
+
private readonly projectAccessKey?: string
|
|
87
|
+
|
|
88
|
+
constructor(hostname: string, chainId: number, rpcUrl: string, fetchImpl?: Fetch, projectAccessKey?: string) {
|
|
89
|
+
this.id = `rpc:${hostname}`
|
|
90
|
+
this.chainId = chainId
|
|
91
|
+
this.projectAccessKey = projectAccessKey
|
|
92
|
+
const effectiveFetch = fetchImpl || (typeof window !== 'undefined' ? window.fetch.bind(window) : undefined)
|
|
93
|
+
if (!effectiveFetch) {
|
|
94
|
+
throw new Error('Fetch implementation is required but not available in this environment.')
|
|
95
|
+
}
|
|
96
|
+
this.fetch = effectiveFetch
|
|
97
|
+
this.client = new GenRelayer(hostname, this.fetch)
|
|
98
|
+
|
|
99
|
+
// Get the chain from the chainId
|
|
100
|
+
const chain = getChain(chainId)
|
|
101
|
+
|
|
102
|
+
// Create viem PublicClient with the provided RPC URL
|
|
103
|
+
this.provider = createPublicClient({
|
|
104
|
+
chain,
|
|
105
|
+
transport: http(rpcUrl),
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
isAvailable(_wallet: Address.Address, chainId: number): Promise<boolean> {
|
|
110
|
+
return Promise.resolve(this.chainId === chainId)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async feeTokens(): Promise<{ isFeeRequired: boolean; tokens?: RpcFeeToken[]; paymentAddress?: Address.Address }> {
|
|
114
|
+
try {
|
|
115
|
+
const { isFeeRequired, tokens, paymentAddress } = await this.client.feeTokens()
|
|
116
|
+
if (isFeeRequired) {
|
|
117
|
+
Address.assert(paymentAddress)
|
|
118
|
+
return {
|
|
119
|
+
isFeeRequired,
|
|
120
|
+
tokens,
|
|
121
|
+
paymentAddress,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Not required
|
|
125
|
+
return {
|
|
126
|
+
isFeeRequired,
|
|
127
|
+
}
|
|
128
|
+
} catch (e) {
|
|
129
|
+
console.warn('RpcRelayer.feeTokens failed:', e)
|
|
130
|
+
return { isFeeRequired: false }
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async feeOptions(
|
|
135
|
+
wallet: Address.Address,
|
|
136
|
+
chainId: number,
|
|
137
|
+
calls: Payload.Call[],
|
|
138
|
+
): Promise<{ options: FeeOption[]; quote?: FeeQuote }> {
|
|
139
|
+
const callsStruct: Payload.Calls = { type: 'call', space: 0n, nonce: 0n, calls: calls }
|
|
140
|
+
const data = Payload.encode(callsStruct)
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
const result = await this.client.feeOptions(
|
|
144
|
+
{
|
|
145
|
+
wallet: wallet,
|
|
146
|
+
to: wallet,
|
|
147
|
+
data: Bytes.toHex(data),
|
|
148
|
+
},
|
|
149
|
+
{ ...(this.projectAccessKey ? { 'X-Access-Key': this.projectAccessKey } : undefined) },
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
const quote = result.quote ? ({ _tag: 'FeeQuote', _quote: result.quote } as FeeQuote) : undefined
|
|
153
|
+
const options = result.options.map((option) => ({
|
|
154
|
+
token: {
|
|
155
|
+
...option.token,
|
|
156
|
+
contractAddress: this.mapRpcFeeTokenToAddress(option.token),
|
|
157
|
+
},
|
|
158
|
+
to: option.to,
|
|
159
|
+
value: option.value,
|
|
160
|
+
gasLimit: option.gasLimit,
|
|
161
|
+
}))
|
|
162
|
+
|
|
163
|
+
return { options, quote }
|
|
164
|
+
} catch (e) {
|
|
165
|
+
console.warn('RpcRelayer.feeOptions failed:', e)
|
|
166
|
+
return { options: [] }
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async sendMetaTxn(
|
|
171
|
+
walletAddress: Address.Address,
|
|
172
|
+
to: Address.Address,
|
|
173
|
+
data: Hex.Hex,
|
|
174
|
+
chainId: number,
|
|
175
|
+
quote?: FeeQuote,
|
|
176
|
+
preconditions?: TransactionPrecondition[],
|
|
177
|
+
): Promise<{ opHash: Hex.Hex }> {
|
|
178
|
+
console.log('sendMetaTxn', walletAddress, to, data, chainId, quote, preconditions)
|
|
179
|
+
const rpcCall: RpcMetaTxn = {
|
|
180
|
+
walletAddress: walletAddress,
|
|
181
|
+
contract: to,
|
|
182
|
+
input: data,
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const result: RpcSendMetaTxnReturn = await this.client.sendMetaTxn(
|
|
186
|
+
{
|
|
187
|
+
call: rpcCall,
|
|
188
|
+
quote: quote ? JSON.stringify(quote._quote) : undefined,
|
|
189
|
+
preconditions: preconditions,
|
|
190
|
+
},
|
|
191
|
+
{ ...(this.projectAccessKey ? { 'X-Access-Key': this.projectAccessKey } : undefined) },
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if (!result.status) {
|
|
195
|
+
console.error('RpcRelayer.relay failed', result)
|
|
196
|
+
throw new Error(`Relay failed: TxnHash ${result.txnHash}`)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return { opHash: Hex.fromString(result.txnHash) }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async relay(
|
|
203
|
+
to: Address.Address,
|
|
204
|
+
data: Hex.Hex,
|
|
205
|
+
chainId: number,
|
|
206
|
+
quote?: FeeQuote,
|
|
207
|
+
preconditions?: TransactionPrecondition[],
|
|
208
|
+
): Promise<{ opHash: Hex.Hex }> {
|
|
209
|
+
console.log('relay', to, data, chainId, quote, preconditions)
|
|
210
|
+
const rpcCall: RpcMetaTxn = {
|
|
211
|
+
walletAddress: to,
|
|
212
|
+
contract: to,
|
|
213
|
+
input: data,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const result: RpcSendMetaTxnReturn = await this.client.sendMetaTxn(
|
|
217
|
+
{
|
|
218
|
+
call: rpcCall,
|
|
219
|
+
quote: quote ? JSON.stringify(quote._quote) : undefined,
|
|
220
|
+
preconditions: preconditions,
|
|
221
|
+
},
|
|
222
|
+
{ ...(this.projectAccessKey ? { 'X-Access-Key': this.projectAccessKey } : undefined) },
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
if (!result.status) {
|
|
226
|
+
console.error('RpcRelayer.relay failed', result)
|
|
227
|
+
throw new Error(`Relay failed: TxnHash ${result.txnHash}`)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { opHash: `0x${result.txnHash}` }
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async status(opHash: Hex.Hex, chainId: number): Promise<OperationStatus> {
|
|
234
|
+
try {
|
|
235
|
+
const cleanedOpHash = opHash.startsWith('0x') ? opHash.substring(2) : opHash
|
|
236
|
+
const result = await this.client.getMetaTxnReceipt({ metaTxID: cleanedOpHash })
|
|
237
|
+
const receipt = result.receipt
|
|
238
|
+
|
|
239
|
+
if (!receipt) {
|
|
240
|
+
console.warn(`RpcRelayer.status: receipt not found for opHash ${opHash}`)
|
|
241
|
+
return { status: 'unknown' }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!receipt.status) {
|
|
245
|
+
console.warn(`RpcRelayer.status: receipt status not found for opHash ${opHash}`)
|
|
246
|
+
return { status: 'unknown' }
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
switch (receipt.status as ETHTxnStatus) {
|
|
250
|
+
case ETHTxnStatus.QUEUED:
|
|
251
|
+
case ETHTxnStatus.PENDING_PRECONDITION:
|
|
252
|
+
case ETHTxnStatus.SENT:
|
|
253
|
+
return { status: 'pending' }
|
|
254
|
+
case ETHTxnStatus.SUCCEEDED:
|
|
255
|
+
return { status: 'confirmed', transactionHash: receipt.txnHash as Hex.Hex, data: result }
|
|
256
|
+
case ETHTxnStatus.FAILED:
|
|
257
|
+
case ETHTxnStatus.PARTIALLY_FAILED:
|
|
258
|
+
return {
|
|
259
|
+
status: 'failed',
|
|
260
|
+
transactionHash: receipt.txnHash ? (receipt.txnHash as Hex.Hex) : undefined,
|
|
261
|
+
reason: receipt.revertReason || 'Relayer reported failure',
|
|
262
|
+
data: result,
|
|
263
|
+
}
|
|
264
|
+
case ETHTxnStatus.DROPPED:
|
|
265
|
+
return { status: 'failed', reason: 'Transaction dropped' }
|
|
266
|
+
case ETHTxnStatus.UNKNOWN:
|
|
267
|
+
default:
|
|
268
|
+
return { status: 'unknown' }
|
|
269
|
+
}
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.error(`RpcRelayer.status failed for opHash ${opHash}:`, error)
|
|
272
|
+
return { status: 'failed', reason: 'Failed to fetch status' }
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async checkPrecondition(precondition: TransactionPrecondition): Promise<boolean> {
|
|
277
|
+
const decoded = decodePrecondition(precondition)
|
|
278
|
+
|
|
279
|
+
if (!decoded) {
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
switch (decoded.type()) {
|
|
284
|
+
case 'native-balance': {
|
|
285
|
+
const native = decoded as any
|
|
286
|
+
try {
|
|
287
|
+
const balance = await this.provider.getBalance({ address: native.address.toString() as `0x${string}` })
|
|
288
|
+
const minWei = native.min !== undefined ? BigInt(native.min) : undefined
|
|
289
|
+
const maxWei = native.max !== undefined ? BigInt(native.max) : undefined
|
|
290
|
+
|
|
291
|
+
if (minWei !== undefined && maxWei !== undefined) {
|
|
292
|
+
return balance >= minWei && balance <= maxWei
|
|
293
|
+
}
|
|
294
|
+
if (minWei !== undefined) {
|
|
295
|
+
return balance >= minWei
|
|
296
|
+
}
|
|
297
|
+
if (maxWei !== undefined) {
|
|
298
|
+
return balance <= maxWei
|
|
299
|
+
}
|
|
300
|
+
// If no min or max specified, this is an invalid precondition
|
|
301
|
+
console.warn('Native balance precondition has neither min nor max specified')
|
|
302
|
+
return false
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.error('Error checking native balance:', error)
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
case 'erc20-balance': {
|
|
310
|
+
const erc20 = decoded as any
|
|
311
|
+
try {
|
|
312
|
+
const data = AbiFunction.encodeData(erc20BalanceOf, [erc20.address.toString()])
|
|
313
|
+
const result = await this.provider.call({
|
|
314
|
+
to: erc20.token.toString() as `0x${string}`,
|
|
315
|
+
data: data as `0x${string}`,
|
|
316
|
+
})
|
|
317
|
+
const balance = BigInt(result.toString())
|
|
318
|
+
const minWei = erc20.min !== undefined ? BigInt(erc20.min) : undefined
|
|
319
|
+
const maxWei = erc20.max !== undefined ? BigInt(erc20.max) : undefined
|
|
320
|
+
|
|
321
|
+
if (minWei !== undefined && maxWei !== undefined) {
|
|
322
|
+
return balance >= minWei && balance <= maxWei
|
|
323
|
+
}
|
|
324
|
+
if (minWei !== undefined) {
|
|
325
|
+
return balance >= minWei
|
|
326
|
+
}
|
|
327
|
+
if (maxWei !== undefined) {
|
|
328
|
+
return balance <= maxWei
|
|
329
|
+
}
|
|
330
|
+
console.warn('ERC20 balance precondition has neither min nor max specified')
|
|
331
|
+
return false
|
|
332
|
+
} catch (error) {
|
|
333
|
+
console.error('Error checking ERC20 balance:', error)
|
|
334
|
+
return false
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
case 'erc20-approval': {
|
|
339
|
+
const erc20 = decoded as any
|
|
340
|
+
try {
|
|
341
|
+
const data = AbiFunction.encodeData(erc20Allowance, [erc20.address.toString(), erc20.operator.toString()])
|
|
342
|
+
const result = await this.provider.call({
|
|
343
|
+
to: erc20.token.toString() as `0x${string}`,
|
|
344
|
+
data: data as `0x${string}`,
|
|
345
|
+
})
|
|
346
|
+
const allowance = BigInt(result.toString())
|
|
347
|
+
const minAllowance = BigInt(erc20.min)
|
|
348
|
+
return allowance >= minAllowance
|
|
349
|
+
} catch (error) {
|
|
350
|
+
console.error('Error checking ERC20 approval:', error)
|
|
351
|
+
return false
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
case 'erc721-ownership': {
|
|
356
|
+
const erc721 = decoded as any
|
|
357
|
+
try {
|
|
358
|
+
const data = AbiFunction.encodeData(erc721OwnerOf, [erc721.tokenId])
|
|
359
|
+
const result = await this.provider.call({
|
|
360
|
+
to: erc721.token.toString() as `0x${string}`,
|
|
361
|
+
data: data as `0x${string}`,
|
|
362
|
+
})
|
|
363
|
+
const resultHex = result.toString() as `0x${string}`
|
|
364
|
+
const owner = resultHex.slice(-40)
|
|
365
|
+
const isOwner = owner.toLowerCase() === erc721.address.toString().slice(2).toLowerCase()
|
|
366
|
+
const expectedOwnership = erc721.owned !== undefined ? erc721.owned : true
|
|
367
|
+
return isOwner === expectedOwnership
|
|
368
|
+
} catch (error) {
|
|
369
|
+
console.error('Error checking ERC721 ownership:', error)
|
|
370
|
+
return false
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
case 'erc721-approval': {
|
|
375
|
+
const erc721 = decoded as any
|
|
376
|
+
try {
|
|
377
|
+
const data = AbiFunction.encodeData(erc721GetApproved, [erc721.tokenId])
|
|
378
|
+
const result = await this.provider.call({
|
|
379
|
+
to: erc721.token.toString() as `0x${string}`,
|
|
380
|
+
data: data as `0x${string}`,
|
|
381
|
+
})
|
|
382
|
+
const resultHex = result.toString() as `0x${string}`
|
|
383
|
+
const approved = resultHex.slice(-40)
|
|
384
|
+
return approved.toLowerCase() === erc721.operator.toString().slice(2).toLowerCase()
|
|
385
|
+
} catch (error) {
|
|
386
|
+
console.error('Error checking ERC721 approval:', error)
|
|
387
|
+
return false
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
case 'erc1155-balance': {
|
|
392
|
+
const erc1155 = decoded as any
|
|
393
|
+
try {
|
|
394
|
+
const data = AbiFunction.encodeData(erc1155BalanceOf, [erc1155.address.toString(), erc1155.tokenId])
|
|
395
|
+
const result = await this.provider.call({
|
|
396
|
+
to: erc1155.token.toString() as `0x${string}`,
|
|
397
|
+
data: data as `0x${string}`,
|
|
398
|
+
})
|
|
399
|
+
const balance = BigInt(result.toString())
|
|
400
|
+
const minWei = erc1155.min !== undefined ? BigInt(erc1155.min) : undefined
|
|
401
|
+
const maxWei = erc1155.max !== undefined ? BigInt(erc1155.max) : undefined
|
|
402
|
+
|
|
403
|
+
if (minWei !== undefined && maxWei !== undefined) {
|
|
404
|
+
return balance >= minWei && balance <= maxWei
|
|
405
|
+
}
|
|
406
|
+
if (minWei !== undefined) {
|
|
407
|
+
return balance >= minWei
|
|
408
|
+
}
|
|
409
|
+
if (maxWei !== undefined) {
|
|
410
|
+
return balance <= maxWei
|
|
411
|
+
}
|
|
412
|
+
console.warn('ERC1155 balance precondition has neither min nor max specified')
|
|
413
|
+
return false
|
|
414
|
+
} catch (error) {
|
|
415
|
+
console.error('Error checking ERC1155 balance:', error)
|
|
416
|
+
return false
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
case 'erc1155-approval': {
|
|
421
|
+
const erc1155 = decoded as any
|
|
422
|
+
try {
|
|
423
|
+
const data = AbiFunction.encodeData(erc1155IsApprovedForAll, [
|
|
424
|
+
erc1155.address.toString(),
|
|
425
|
+
erc1155.operator.toString(),
|
|
426
|
+
])
|
|
427
|
+
const result = await this.provider.call({
|
|
428
|
+
to: erc1155.token.toString() as `0x${string}`,
|
|
429
|
+
data: data as `0x${string}`,
|
|
430
|
+
})
|
|
431
|
+
return BigInt(result.toString()) === 1n
|
|
432
|
+
} catch (error) {
|
|
433
|
+
console.error('Error checking ERC1155 approval:', error)
|
|
434
|
+
return false
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
default:
|
|
439
|
+
return false
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
private mapRpcFeeTokenToAddress(rpcToken: RpcFeeToken): Address.Address {
|
|
444
|
+
if (rpcToken.type === FeeTokenType.ERC20_TOKEN && rpcToken.contractAddress) {
|
|
445
|
+
return Address.from(rpcToken.contractAddress)
|
|
446
|
+
}
|
|
447
|
+
return Constants.ZeroAddress // Default to zero address for native token or unsupported types
|
|
448
|
+
}
|
|
449
|
+
}
|