@0xsequence/relayer 3.0.0-beta.8 → 3.0.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/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +134 -0
- package/dist/preconditions/codec.d.ts.map +1 -1
- package/dist/preconditions/codec.js +55 -45
- package/dist/relayer/relayer.d.ts +2 -2
- package/dist/relayer/relayer.d.ts.map +1 -1
- package/dist/relayer/relayer.js +3 -1
- package/dist/relayer/rpc-relayer/index.d.ts +3 -3
- package/dist/relayer/rpc-relayer/index.d.ts.map +1 -1
- package/dist/relayer/rpc-relayer/index.js +26 -25
- package/dist/relayer/standard/eip6963.d.ts +2 -2
- package/dist/relayer/standard/eip6963.d.ts.map +1 -1
- package/dist/relayer/standard/eip6963.js +3 -3
- package/dist/relayer/standard/local.d.ts +2 -3
- package/dist/relayer/standard/local.d.ts.map +1 -1
- package/dist/relayer/standard/local.js +14 -30
- package/dist/relayer/standard/pk-relayer.d.ts +3 -3
- package/dist/relayer/standard/pk-relayer.d.ts.map +1 -1
- package/dist/relayer/standard/pk-relayer.js +3 -3
- package/dist/relayer/standard/sequence.d.ts +3 -3
- package/dist/relayer/standard/sequence.d.ts.map +1 -1
- package/dist/relayer/standard/sequence.js +2 -3
- package/eslint.config.js +4 -0
- package/package.json +9 -7
- package/src/preconditions/codec.ts +63 -39
- package/src/relayer/relayer.ts +4 -1
- package/src/relayer/rpc-relayer/index.ts +50 -33
- package/src/relayer/standard/eip6963.ts +4 -3
- package/src/relayer/standard/local.ts +37 -44
- package/src/relayer/standard/pk-relayer.ts +4 -3
- package/src/relayer/standard/sequence.ts +3 -3
- package/test/preconditions/codec.test.ts +11 -11
- package/test/preconditions/preconditions.test.ts +97 -138
- package/test/preconditions/selectors.test.ts +76 -254
- package/test/preconditions/types.test.ts +6 -6
- package/test/relayer/relayer.test.ts +4 -4
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Payload } from '@0xsequence/wallet-primitives'
|
|
2
2
|
import { EIP1193Provider } from 'mipd'
|
|
3
|
-
import { AbiFunction, Address,
|
|
3
|
+
import { AbiFunction, Address, Hex, TransactionReceipt } from 'ox'
|
|
4
4
|
import { FeeOption, FeeQuote, OperationStatus, Relayer } from '../index.js'
|
|
5
5
|
import { FeeToken, TransactionPrecondition } from '../rpc-relayer/relayer.gen.js'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
decodePrecondition,
|
|
8
|
+
Erc1155ApprovalPrecondition,
|
|
9
|
+
Erc1155BalancePrecondition,
|
|
10
|
+
Erc20ApprovalPrecondition,
|
|
11
|
+
Erc20BalancePrecondition,
|
|
12
|
+
Erc721ApprovalPrecondition,
|
|
13
|
+
Erc721OwnershipPrecondition,
|
|
14
|
+
NativeBalancePrecondition,
|
|
15
|
+
} from '../../preconditions/index.js'
|
|
7
16
|
import {
|
|
8
17
|
erc20BalanceOf,
|
|
9
18
|
erc20Allowance,
|
|
@@ -23,7 +32,7 @@ export interface GenericProvider {
|
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
export class LocalRelayer implements Relayer {
|
|
26
|
-
public readonly kind
|
|
35
|
+
public readonly kind = 'relayer'
|
|
27
36
|
public readonly type = 'local'
|
|
28
37
|
public readonly id = 'local'
|
|
29
38
|
|
|
@@ -34,7 +43,7 @@ export class LocalRelayer implements Relayer {
|
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
static createFromWindow(window: Window): LocalRelayer | undefined {
|
|
37
|
-
const eth = (window as
|
|
46
|
+
const eth = (window as { ethereum?: EIP1193Provider }).ethereum
|
|
38
47
|
if (!eth) {
|
|
39
48
|
console.warn('Window.ethereum not found, skipping local relayer')
|
|
40
49
|
return undefined
|
|
@@ -54,27 +63,14 @@ export class LocalRelayer implements Relayer {
|
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
feeOptions(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
_wallet: Address.Address,
|
|
67
|
+
_chainId: number,
|
|
68
|
+
_to: Address.Address,
|
|
69
|
+
_calls: Payload.Call[],
|
|
60
70
|
): Promise<{ options: FeeOption[]; quote?: FeeQuote }> {
|
|
61
71
|
return Promise.resolve({ options: [] })
|
|
62
72
|
}
|
|
63
73
|
|
|
64
|
-
private decodeCalls(data: Hex.Hex): Payload.Calls {
|
|
65
|
-
const executeSelector = AbiFunction.getSelector(Constants.EXECUTE)
|
|
66
|
-
|
|
67
|
-
let packedPayload
|
|
68
|
-
if (data.startsWith(executeSelector)) {
|
|
69
|
-
const decode = AbiFunction.decodeData(Constants.EXECUTE, data)
|
|
70
|
-
packedPayload = decode[0]
|
|
71
|
-
} else {
|
|
72
|
-
packedPayload = data
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return Payload.decode(Bytes.fromHex(packedPayload))
|
|
76
|
-
}
|
|
77
|
-
|
|
78
74
|
async relay(
|
|
79
75
|
to: Address.Address,
|
|
80
76
|
data: Hex.Hex,
|
|
@@ -177,8 +173,8 @@ export class LocalRelayer implements Relayer {
|
|
|
177
173
|
|
|
178
174
|
switch (decoded.type()) {
|
|
179
175
|
case 'native-balance': {
|
|
180
|
-
const native = decoded as
|
|
181
|
-
const balance = await this.provider.getBalance(native.address
|
|
176
|
+
const native = decoded as NativeBalancePrecondition
|
|
177
|
+
const balance = await this.provider.getBalance(native.address)
|
|
182
178
|
if (native.min !== undefined && balance < native.min) {
|
|
183
179
|
return false
|
|
184
180
|
}
|
|
@@ -189,10 +185,10 @@ export class LocalRelayer implements Relayer {
|
|
|
189
185
|
}
|
|
190
186
|
|
|
191
187
|
case 'erc20-balance': {
|
|
192
|
-
const erc20 = decoded as
|
|
193
|
-
const data = AbiFunction.encodeData(erc20BalanceOf, [erc20.address
|
|
188
|
+
const erc20 = decoded as Erc20BalancePrecondition
|
|
189
|
+
const data = AbiFunction.encodeData(erc20BalanceOf, [erc20.address])
|
|
194
190
|
const result = await this.provider.call({
|
|
195
|
-
to: erc20.token
|
|
191
|
+
to: erc20.token,
|
|
196
192
|
data,
|
|
197
193
|
})
|
|
198
194
|
const balance = BigInt(result)
|
|
@@ -206,10 +202,10 @@ export class LocalRelayer implements Relayer {
|
|
|
206
202
|
}
|
|
207
203
|
|
|
208
204
|
case 'erc20-approval': {
|
|
209
|
-
const erc20 = decoded as
|
|
210
|
-
const data = AbiFunction.encodeData(erc20Allowance, [erc20.address
|
|
205
|
+
const erc20 = decoded as Erc20ApprovalPrecondition
|
|
206
|
+
const data = AbiFunction.encodeData(erc20Allowance, [erc20.address, erc20.operator])
|
|
211
207
|
const result = await this.provider.call({
|
|
212
|
-
to: erc20.token
|
|
208
|
+
to: erc20.token,
|
|
213
209
|
data,
|
|
214
210
|
})
|
|
215
211
|
const allowance = BigInt(result)
|
|
@@ -217,10 +213,10 @@ export class LocalRelayer implements Relayer {
|
|
|
217
213
|
}
|
|
218
214
|
|
|
219
215
|
case 'erc721-ownership': {
|
|
220
|
-
const erc721 = decoded as
|
|
216
|
+
const erc721 = decoded as Erc721OwnershipPrecondition
|
|
221
217
|
const data = AbiFunction.encodeData(erc721OwnerOf, [erc721.tokenId])
|
|
222
218
|
const result = await this.provider.call({
|
|
223
|
-
to: erc721.token
|
|
219
|
+
to: erc721.token,
|
|
224
220
|
data,
|
|
225
221
|
})
|
|
226
222
|
const owner = '0x' + result.slice(26)
|
|
@@ -229,10 +225,10 @@ export class LocalRelayer implements Relayer {
|
|
|
229
225
|
}
|
|
230
226
|
|
|
231
227
|
case 'erc721-approval': {
|
|
232
|
-
const erc721 = decoded as
|
|
228
|
+
const erc721 = decoded as Erc721ApprovalPrecondition
|
|
233
229
|
const data = AbiFunction.encodeData(erc721GetApproved, [erc721.tokenId])
|
|
234
230
|
const result = await this.provider.call({
|
|
235
|
-
to: erc721.token
|
|
231
|
+
to: erc721.token,
|
|
236
232
|
data,
|
|
237
233
|
})
|
|
238
234
|
const approved = '0x' + result.slice(26)
|
|
@@ -240,10 +236,10 @@ export class LocalRelayer implements Relayer {
|
|
|
240
236
|
}
|
|
241
237
|
|
|
242
238
|
case 'erc1155-balance': {
|
|
243
|
-
const erc1155 = decoded as
|
|
244
|
-
const data = AbiFunction.encodeData(erc1155BalanceOf, [erc1155.address
|
|
239
|
+
const erc1155 = decoded as Erc1155BalancePrecondition
|
|
240
|
+
const data = AbiFunction.encodeData(erc1155BalanceOf, [erc1155.address, erc1155.tokenId])
|
|
245
241
|
const result = await this.provider.call({
|
|
246
|
-
to: erc1155.token
|
|
242
|
+
to: erc1155.token,
|
|
247
243
|
data,
|
|
248
244
|
})
|
|
249
245
|
const balance = BigInt(result)
|
|
@@ -257,13 +253,10 @@ export class LocalRelayer implements Relayer {
|
|
|
257
253
|
}
|
|
258
254
|
|
|
259
255
|
case 'erc1155-approval': {
|
|
260
|
-
const erc1155 = decoded as
|
|
261
|
-
const data = AbiFunction.encodeData(erc1155IsApprovedForAll, [
|
|
262
|
-
erc1155.address.toString(),
|
|
263
|
-
erc1155.operator.toString(),
|
|
264
|
-
])
|
|
256
|
+
const erc1155 = decoded as Erc1155ApprovalPrecondition
|
|
257
|
+
const data = AbiFunction.encodeData(erc1155IsApprovedForAll, [erc1155.address, erc1155.operator])
|
|
265
258
|
const result = await this.provider.call({
|
|
266
|
-
to: erc1155.token
|
|
259
|
+
to: erc1155.token,
|
|
267
260
|
data,
|
|
268
261
|
})
|
|
269
262
|
return BigInt(result) === 1n
|
|
@@ -340,7 +333,7 @@ export class EIP1193ProviderAdapter implements GenericProvider {
|
|
|
340
333
|
const rpcReceipt = await this.provider.request({ method: 'eth_getTransactionReceipt', params: [txHash] })
|
|
341
334
|
|
|
342
335
|
if (rpcReceipt) {
|
|
343
|
-
const receipt = TransactionReceipt.fromRpc(rpcReceipt as
|
|
336
|
+
const receipt = TransactionReceipt.fromRpc(rpcReceipt as Parameters<typeof TransactionReceipt.fromRpc>[0])
|
|
344
337
|
if (receipt?.status === 'success') {
|
|
345
338
|
return 'success'
|
|
346
339
|
} else if (receipt?.status === 'reverted') {
|
|
@@ -5,7 +5,7 @@ import { FeeOption, FeeQuote, OperationStatus, Relayer } from '../index.js'
|
|
|
5
5
|
import { FeeToken } from '../rpc-relayer/relayer.gen.js'
|
|
6
6
|
|
|
7
7
|
export class PkRelayer implements Relayer {
|
|
8
|
-
public readonly kind
|
|
8
|
+
public readonly kind = 'relayer'
|
|
9
9
|
public readonly type = 'pk'
|
|
10
10
|
public readonly id = 'pk'
|
|
11
11
|
private readonly relayer: LocalRelayer
|
|
@@ -114,9 +114,10 @@ export class PkRelayer implements Relayer {
|
|
|
114
114
|
feeOptions(
|
|
115
115
|
wallet: Address.Address,
|
|
116
116
|
chainId: number,
|
|
117
|
+
to: Address.Address,
|
|
117
118
|
calls: Payload.Call[],
|
|
118
119
|
): Promise<{ options: FeeOption[]; quote?: FeeQuote }> {
|
|
119
|
-
return this.relayer.feeOptions(wallet, chainId, calls)
|
|
120
|
+
return this.relayer.feeOptions(wallet, chainId, to, calls)
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
async relay(to: Address.Address, data: Hex.Hex, chainId: number, _?: FeeQuote): Promise<{ opHash: Hex.Hex }> {
|
|
@@ -131,7 +132,7 @@ export class PkRelayer implements Relayer {
|
|
|
131
132
|
return this.relayer.status(opHash, chainId)
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
async checkPrecondition(
|
|
135
|
+
async checkPrecondition(_precondition: Precondition.Precondition): Promise<boolean> {
|
|
135
136
|
// TODO: Implement precondition check
|
|
136
137
|
return true
|
|
137
138
|
}
|
|
@@ -3,7 +3,7 @@ import { Payload } from '@0xsequence/wallet-primitives'
|
|
|
3
3
|
import { AbiFunction, Address, Bytes, Hex } from 'ox'
|
|
4
4
|
import { FeeOption, FeeQuote, OperationStatus, Relayer } from '../index.js'
|
|
5
5
|
export class SequenceRelayer implements Relayer {
|
|
6
|
-
public readonly kind
|
|
6
|
+
public readonly kind = 'relayer'
|
|
7
7
|
public readonly type = 'sequence'
|
|
8
8
|
readonly id = 'sequence'
|
|
9
9
|
|
|
@@ -36,9 +36,9 @@ export class SequenceRelayer implements Relayer {
|
|
|
36
36
|
async feeOptions(
|
|
37
37
|
wallet: Address.Address,
|
|
38
38
|
_chainId: number,
|
|
39
|
+
to: Address.Address,
|
|
39
40
|
calls: Payload.Call[],
|
|
40
41
|
): Promise<{ options: FeeOption[]; quote?: FeeQuote }> {
|
|
41
|
-
const to = wallet // TODO: this might be the guest module
|
|
42
42
|
const execute = AbiFunction.from('function execute(bytes calldata _payload, bytes calldata _signature)')
|
|
43
43
|
const payload = Payload.encode({ type: 'call', space: 0n, nonce: 0n, calls }, to)
|
|
44
44
|
const signature = '0x0001' // TODO: use a stub signature
|
|
@@ -52,7 +52,7 @@ export class SequenceRelayer implements Relayer {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
async checkPrecondition(
|
|
55
|
+
async checkPrecondition(_precondition: TransactionPrecondition): Promise<boolean> {
|
|
56
56
|
// TODO: implement
|
|
57
57
|
return false
|
|
58
58
|
}
|
|
@@ -36,8 +36,8 @@ describe('Preconditions Codec', () => {
|
|
|
36
36
|
|
|
37
37
|
describe('decodePrecondition', () => {
|
|
38
38
|
it('should return undefined for null/undefined input', () => {
|
|
39
|
-
expect(decodePrecondition(null as
|
|
40
|
-
expect(decodePrecondition(undefined as
|
|
39
|
+
expect(decodePrecondition(null as unknown as TransactionPrecondition)).toBeUndefined()
|
|
40
|
+
expect(decodePrecondition(undefined as unknown as TransactionPrecondition)).toBeUndefined()
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
it('should decode native balance precondition with only min', () => {
|
|
@@ -231,8 +231,8 @@ describe('Preconditions Codec', () => {
|
|
|
231
231
|
it('should handle malformed addresses gracefully', () => {
|
|
232
232
|
const intent: TransactionPrecondition = {
|
|
233
233
|
type: 'native-balance',
|
|
234
|
-
ownerAddress: 'invalid-address'
|
|
235
|
-
tokenAddress: NATIVE_TOKEN_ADDRESS,
|
|
234
|
+
ownerAddress: 'invalid-address',
|
|
235
|
+
tokenAddress: NATIVE_TOKEN_ADDRESS.toString(),
|
|
236
236
|
chainId: ARBITRUM_CHAIN_ID,
|
|
237
237
|
minAmount: BigInt('1000000000000000000'),
|
|
238
238
|
}
|
|
@@ -243,13 +243,13 @@ describe('Preconditions Codec', () => {
|
|
|
243
243
|
})
|
|
244
244
|
|
|
245
245
|
it('should handle malformed BigInt values gracefully', () => {
|
|
246
|
-
const intent
|
|
246
|
+
const intent = {
|
|
247
247
|
type: 'native-balance',
|
|
248
|
-
ownerAddress: TEST_ADDRESS,
|
|
249
|
-
tokenAddress: NATIVE_TOKEN_ADDRESS,
|
|
248
|
+
ownerAddress: TEST_ADDRESS.toString(),
|
|
249
|
+
tokenAddress: NATIVE_TOKEN_ADDRESS.toString(),
|
|
250
250
|
chainId: ARBITRUM_CHAIN_ID,
|
|
251
|
-
minAmount: 'not-a-number'
|
|
252
|
-
}
|
|
251
|
+
minAmount: 'not-a-number',
|
|
252
|
+
} as unknown as TransactionPrecondition
|
|
253
253
|
|
|
254
254
|
const result = decodePrecondition(intent)
|
|
255
255
|
expect(result).toBeUndefined()
|
|
@@ -316,8 +316,8 @@ describe('Preconditions Codec', () => {
|
|
|
316
316
|
},
|
|
317
317
|
{
|
|
318
318
|
type: 'native-balance',
|
|
319
|
-
ownerAddress: 'invalid-address'
|
|
320
|
-
tokenAddress: NATIVE_TOKEN_ADDRESS,
|
|
319
|
+
ownerAddress: 'invalid-address',
|
|
320
|
+
tokenAddress: NATIVE_TOKEN_ADDRESS.toString(),
|
|
321
321
|
chainId: ARBITRUM_CHAIN_ID,
|
|
322
322
|
minAmount: BigInt('1000000000000000000'),
|
|
323
323
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address,
|
|
1
|
+
import { Address, Hex, Secp256k1 } from 'ox'
|
|
2
2
|
import { describe, expect, it, vi } from 'vitest'
|
|
3
3
|
import {
|
|
4
4
|
Erc1155ApprovalPrecondition,
|
|
@@ -9,49 +9,50 @@ import {
|
|
|
9
9
|
Erc721OwnershipPrecondition,
|
|
10
10
|
NativeBalancePrecondition,
|
|
11
11
|
} from '../../src/preconditions/types.js'
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import {
|
|
13
|
+
LocalRelayer,
|
|
14
|
+
type GenericProvider,
|
|
15
|
+
} from '../../src/relayer/standard/local.js'
|
|
14
16
|
import { Network } from '@0xsequence/wallet-primitives'
|
|
15
17
|
|
|
18
|
+
const CAN_RUN_LIVE = false
|
|
19
|
+
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
|
16
20
|
const ERC20_IMPLICIT_MINT_CONTRACT = '0x041E0CDC028050519C8e6485B2d9840caf63773F'
|
|
17
21
|
|
|
18
22
|
function randomAddress(): Address.Address {
|
|
19
23
|
return Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey: Secp256k1.randomPrivateKey() }))
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
function createMockProvider(): GenericProvider {
|
|
27
|
+
return {
|
|
28
|
+
sendTransaction: vi.fn(),
|
|
29
|
+
getBalance: vi.fn(),
|
|
30
|
+
call: vi.fn(),
|
|
31
|
+
getTransactionReceipt: vi.fn(),
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
describe('Preconditions', () => {
|
|
23
|
-
const getProvider = async (): Promise<{ provider:
|
|
24
|
-
|
|
25
|
-
let chainId: number = Network.ChainId.MAINNET
|
|
36
|
+
const getProvider = async (): Promise<{ provider: GenericProvider; chainId: number }> => {
|
|
37
|
+
const chainId = Network.ChainId.MAINNET
|
|
26
38
|
if (CAN_RUN_LIVE) {
|
|
27
|
-
|
|
28
|
-
chainId = Number(await provider.request({ method: 'eth_chainId' }))
|
|
29
|
-
} else {
|
|
30
|
-
provider = {
|
|
31
|
-
request: vi.fn(),
|
|
32
|
-
on: vi.fn(),
|
|
33
|
-
removeListener: vi.fn(),
|
|
34
|
-
call: vi.fn(),
|
|
35
|
-
sendTransaction: vi.fn(),
|
|
36
|
-
getBalance: vi.fn(),
|
|
37
|
-
} as unknown as Provider.Provider
|
|
39
|
+
throw new Error('Live tests not configured: set up RPC and GenericProvider adapter')
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
return { provider
|
|
41
|
+
const provider = createMockProvider()
|
|
42
|
+
return { provider, chainId }
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
const testWalletAddress = randomAddress()
|
|
44
46
|
|
|
45
|
-
const requireContractDeployed = async (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
throw new Error(`Contract ${contract} not deployed`)
|
|
47
|
+
const requireContractDeployed = async (_provider: GenericProvider, _contract: Address.Address) => {
|
|
48
|
+
if (CAN_RUN_LIVE) {
|
|
49
|
+
throw new Error('Live contract check not implemented')
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
it('should create and check native balance precondition', async () => {
|
|
53
54
|
const { provider, chainId } = await getProvider()
|
|
54
|
-
const relayer = new LocalRelayer(provider
|
|
55
|
+
const relayer = new LocalRelayer(provider)
|
|
55
56
|
|
|
56
57
|
const precondition = new NativeBalancePrecondition(
|
|
57
58
|
testWalletAddress,
|
|
@@ -59,225 +60,183 @@ describe('Preconditions', () => {
|
|
|
59
60
|
2000000000000000000n, // 2 ETH max
|
|
60
61
|
)
|
|
61
62
|
|
|
62
|
-
const
|
|
63
|
+
const transactionPrecondition = {
|
|
63
64
|
type: precondition.type(),
|
|
64
|
-
chainId
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
max: precondition.max?.toString(),
|
|
69
|
-
}),
|
|
65
|
+
chainId,
|
|
66
|
+
ownerAddress: precondition.address.toString(),
|
|
67
|
+
tokenAddress: ZERO_ADDRESS,
|
|
68
|
+
minAmount: precondition.min ?? 0n,
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
// Mock the balance check
|
|
74
|
-
;(provider as any).request.mockResolvedValue('0x16345785d8a0000') // 1.5 ETH in hex
|
|
75
|
-
}
|
|
71
|
+
vi.mocked(provider.getBalance).mockResolvedValue(1500000000000000000n) // 1.5 ETH
|
|
76
72
|
|
|
77
|
-
const isValid = await relayer.checkPrecondition(
|
|
73
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
78
74
|
expect(isValid).toBe(true)
|
|
79
75
|
})
|
|
80
76
|
|
|
81
77
|
it('should create and check ERC20 balance precondition', async () => {
|
|
82
78
|
const { provider, chainId } = await getProvider()
|
|
83
|
-
const relayer = new LocalRelayer(provider
|
|
84
|
-
await requireContractDeployed(provider, ERC20_IMPLICIT_MINT_CONTRACT)
|
|
79
|
+
const relayer = new LocalRelayer(provider)
|
|
80
|
+
await requireContractDeployed(provider, Address.from(ERC20_IMPLICIT_MINT_CONTRACT))
|
|
85
81
|
|
|
86
82
|
const precondition = new Erc20BalancePrecondition(
|
|
87
83
|
testWalletAddress,
|
|
88
|
-
ERC20_IMPLICIT_MINT_CONTRACT,
|
|
84
|
+
Address.from(ERC20_IMPLICIT_MINT_CONTRACT),
|
|
89
85
|
1000000n, // 1 token min
|
|
90
86
|
2000000n, // 2 tokens max
|
|
91
87
|
)
|
|
92
88
|
|
|
93
|
-
const
|
|
89
|
+
const transactionPrecondition = {
|
|
94
90
|
type: precondition.type(),
|
|
95
|
-
chainId
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
min: precondition.min?.toString(),
|
|
100
|
-
max: precondition.max?.toString(),
|
|
101
|
-
}),
|
|
91
|
+
chainId,
|
|
92
|
+
ownerAddress: precondition.address.toString(),
|
|
93
|
+
tokenAddress: precondition.token.toString(),
|
|
94
|
+
minAmount: precondition.min ?? 0n,
|
|
102
95
|
}
|
|
103
96
|
|
|
104
|
-
|
|
105
|
-
// Mock the balanceOf call
|
|
106
|
-
;(provider as any).call.mockResolvedValue('0x1e8480') // 1.5 tokens in hex
|
|
107
|
-
}
|
|
97
|
+
vi.mocked(provider.call).mockResolvedValue('0x1e8480' as Hex.Hex) // 1.5 tokens in hex
|
|
108
98
|
|
|
109
|
-
const isValid = await relayer.checkPrecondition(
|
|
99
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
110
100
|
expect(isValid).toBe(true)
|
|
111
101
|
})
|
|
112
102
|
|
|
113
103
|
it('should create and check ERC20 approval precondition', async () => {
|
|
114
104
|
const { provider, chainId } = await getProvider()
|
|
115
|
-
const relayer = new LocalRelayer(provider
|
|
116
|
-
await requireContractDeployed(provider, ERC20_IMPLICIT_MINT_CONTRACT)
|
|
105
|
+
const relayer = new LocalRelayer(provider)
|
|
106
|
+
await requireContractDeployed(provider, Address.from(ERC20_IMPLICIT_MINT_CONTRACT))
|
|
117
107
|
|
|
118
108
|
const operator = randomAddress()
|
|
119
109
|
const precondition = new Erc20ApprovalPrecondition(
|
|
120
110
|
testWalletAddress,
|
|
121
|
-
ERC20_IMPLICIT_MINT_CONTRACT,
|
|
111
|
+
Address.from(ERC20_IMPLICIT_MINT_CONTRACT),
|
|
122
112
|
operator,
|
|
123
113
|
1000000n, // 1 token min approval
|
|
124
114
|
)
|
|
125
115
|
|
|
126
|
-
const
|
|
116
|
+
const transactionPrecondition = {
|
|
127
117
|
type: precondition.type(),
|
|
128
|
-
chainId
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
operator: precondition.operator.toString(),
|
|
133
|
-
min: precondition.min.toString(),
|
|
134
|
-
}),
|
|
118
|
+
chainId,
|
|
119
|
+
ownerAddress: precondition.address.toString(),
|
|
120
|
+
tokenAddress: precondition.token.toString(),
|
|
121
|
+
minAmount: precondition.min,
|
|
135
122
|
}
|
|
136
123
|
|
|
137
|
-
|
|
138
|
-
// Mock the allowance call
|
|
139
|
-
;(provider as any).call.mockResolvedValue('0x1e8480') // 1.5 tokens in hex
|
|
140
|
-
}
|
|
124
|
+
vi.mocked(provider.call).mockResolvedValue('0x1e8480' as Hex.Hex) // 1.5 tokens in hex
|
|
141
125
|
|
|
142
|
-
const isValid = await relayer.checkPrecondition(
|
|
126
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
143
127
|
expect(isValid).toBe(true)
|
|
144
128
|
})
|
|
145
129
|
|
|
146
130
|
it('should create and check ERC721 ownership precondition', async () => {
|
|
147
131
|
const { provider, chainId } = await getProvider()
|
|
148
|
-
const relayer = new LocalRelayer(provider
|
|
149
|
-
await requireContractDeployed(provider, ERC20_IMPLICIT_MINT_CONTRACT)
|
|
132
|
+
const relayer = new LocalRelayer(provider)
|
|
133
|
+
await requireContractDeployed(provider, Address.from(ERC20_IMPLICIT_MINT_CONTRACT))
|
|
150
134
|
|
|
151
135
|
const precondition = new Erc721OwnershipPrecondition(
|
|
152
136
|
testWalletAddress,
|
|
153
|
-
ERC20_IMPLICIT_MINT_CONTRACT,
|
|
137
|
+
Address.from(ERC20_IMPLICIT_MINT_CONTRACT),
|
|
154
138
|
1n, // tokenId
|
|
155
139
|
true, // must own
|
|
156
140
|
)
|
|
157
141
|
|
|
158
|
-
const
|
|
142
|
+
const transactionPrecondition = {
|
|
159
143
|
type: precondition.type(),
|
|
160
|
-
chainId
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
tokenId: precondition.tokenId.toString(),
|
|
165
|
-
owned: precondition.owned,
|
|
166
|
-
}),
|
|
144
|
+
chainId,
|
|
145
|
+
ownerAddress: precondition.address.toString(),
|
|
146
|
+
tokenAddress: precondition.token.toString(),
|
|
147
|
+
minAmount: 0n,
|
|
167
148
|
}
|
|
168
149
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
'0x000000000000000000000000' + testWalletAddress.toString().slice(2).toLowerCase(),
|
|
173
|
-
)
|
|
174
|
-
}
|
|
150
|
+
vi.mocked(provider.call).mockResolvedValue(
|
|
151
|
+
('0x000000000000000000000000' + testWalletAddress.toString().slice(2).toLowerCase()) as Hex.Hex,
|
|
152
|
+
)
|
|
175
153
|
|
|
176
|
-
const isValid = await relayer.checkPrecondition(
|
|
154
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
177
155
|
expect(isValid).toBe(true)
|
|
178
156
|
})
|
|
179
157
|
|
|
180
158
|
it('should create and check ERC721 approval precondition', async () => {
|
|
181
159
|
const { provider, chainId } = await getProvider()
|
|
182
|
-
const relayer = new LocalRelayer(provider
|
|
183
|
-
await requireContractDeployed(provider, ERC20_IMPLICIT_MINT_CONTRACT)
|
|
160
|
+
const relayer = new LocalRelayer(provider)
|
|
161
|
+
await requireContractDeployed(provider, Address.from(ERC20_IMPLICIT_MINT_CONTRACT))
|
|
184
162
|
|
|
185
163
|
const operator = randomAddress()
|
|
186
164
|
const precondition = new Erc721ApprovalPrecondition(
|
|
187
165
|
testWalletAddress,
|
|
188
|
-
ERC20_IMPLICIT_MINT_CONTRACT,
|
|
166
|
+
Address.from(ERC20_IMPLICIT_MINT_CONTRACT),
|
|
189
167
|
1n, // tokenId
|
|
190
168
|
operator,
|
|
191
169
|
)
|
|
192
170
|
|
|
193
|
-
const
|
|
171
|
+
const transactionPrecondition = {
|
|
194
172
|
type: precondition.type(),
|
|
195
|
-
chainId
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
tokenId: precondition.tokenId.toString(),
|
|
200
|
-
operator: precondition.operator.toString(),
|
|
201
|
-
}),
|
|
173
|
+
chainId,
|
|
174
|
+
ownerAddress: precondition.address.toString(),
|
|
175
|
+
tokenAddress: precondition.token.toString(),
|
|
176
|
+
minAmount: 0n,
|
|
202
177
|
}
|
|
203
178
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
)
|
|
209
|
-
}
|
|
179
|
+
// getApproved returns 32-byte word: 12 zero bytes + 20-byte address. Codec uses ownerAddress as operator.
|
|
180
|
+
const approvedHex =
|
|
181
|
+
'0x' + '0'.repeat(24) + testWalletAddress.toString().slice(2).toLowerCase()
|
|
182
|
+
vi.mocked(provider.call).mockResolvedValue(approvedHex as Hex.Hex)
|
|
210
183
|
|
|
211
|
-
const isValid = await relayer.checkPrecondition(
|
|
184
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
212
185
|
expect(isValid).toBe(true)
|
|
213
186
|
})
|
|
214
187
|
|
|
215
188
|
it('should create and check ERC1155 balance precondition', async () => {
|
|
216
189
|
const { provider, chainId } = await getProvider()
|
|
217
|
-
const relayer = new LocalRelayer(provider
|
|
218
|
-
await requireContractDeployed(provider, ERC20_IMPLICIT_MINT_CONTRACT)
|
|
190
|
+
const relayer = new LocalRelayer(provider)
|
|
191
|
+
await requireContractDeployed(provider, Address.from(ERC20_IMPLICIT_MINT_CONTRACT))
|
|
219
192
|
|
|
220
193
|
const precondition = new Erc1155BalancePrecondition(
|
|
221
194
|
testWalletAddress,
|
|
222
|
-
ERC20_IMPLICIT_MINT_CONTRACT,
|
|
195
|
+
Address.from(ERC20_IMPLICIT_MINT_CONTRACT),
|
|
223
196
|
1n, // tokenId
|
|
224
197
|
1000000n, // 1 token min
|
|
225
198
|
2000000n, // 2 tokens max
|
|
226
199
|
)
|
|
227
200
|
|
|
228
|
-
const
|
|
201
|
+
const transactionPrecondition = {
|
|
229
202
|
type: precondition.type(),
|
|
230
|
-
chainId
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
tokenId: precondition.tokenId.toString(),
|
|
235
|
-
min: precondition.min?.toString(),
|
|
236
|
-
max: precondition.max?.toString(),
|
|
237
|
-
}),
|
|
203
|
+
chainId,
|
|
204
|
+
ownerAddress: precondition.address.toString(),
|
|
205
|
+
tokenAddress: precondition.token.toString(),
|
|
206
|
+
minAmount: precondition.min ?? 0n,
|
|
238
207
|
}
|
|
239
208
|
|
|
240
|
-
|
|
241
|
-
// Mock the balanceOf call
|
|
242
|
-
;(provider as any).call.mockResolvedValue('0x1e8480') // 1.5 tokens in hex
|
|
243
|
-
}
|
|
209
|
+
vi.mocked(provider.call).mockResolvedValue('0x1e8480' as Hex.Hex) // 1.5 tokens in hex
|
|
244
210
|
|
|
245
|
-
const isValid = await relayer.checkPrecondition(
|
|
211
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
246
212
|
expect(isValid).toBe(true)
|
|
247
213
|
})
|
|
248
214
|
|
|
249
215
|
it('should create and check ERC1155 approval precondition', async () => {
|
|
250
216
|
const { provider, chainId } = await getProvider()
|
|
251
|
-
const relayer = new LocalRelayer(provider
|
|
252
|
-
await requireContractDeployed(provider, ERC20_IMPLICIT_MINT_CONTRACT)
|
|
217
|
+
const relayer = new LocalRelayer(provider)
|
|
218
|
+
await requireContractDeployed(provider, Address.from(ERC20_IMPLICIT_MINT_CONTRACT))
|
|
253
219
|
|
|
254
220
|
const operator = randomAddress()
|
|
255
221
|
const precondition = new Erc1155ApprovalPrecondition(
|
|
256
222
|
testWalletAddress,
|
|
257
|
-
ERC20_IMPLICIT_MINT_CONTRACT,
|
|
223
|
+
Address.from(ERC20_IMPLICIT_MINT_CONTRACT),
|
|
258
224
|
1n, // tokenId
|
|
259
225
|
operator,
|
|
260
226
|
1000000n, // 1 token min approval
|
|
261
227
|
)
|
|
262
228
|
|
|
263
|
-
const
|
|
229
|
+
const transactionPrecondition = {
|
|
264
230
|
type: precondition.type(),
|
|
265
|
-
chainId
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
tokenId: precondition.tokenId.toString(),
|
|
270
|
-
operator: precondition.operator.toString(),
|
|
271
|
-
min: precondition.min.toString(),
|
|
272
|
-
}),
|
|
231
|
+
chainId,
|
|
232
|
+
ownerAddress: precondition.address.toString(),
|
|
233
|
+
tokenAddress: precondition.token.toString(),
|
|
234
|
+
minAmount: precondition.min,
|
|
273
235
|
}
|
|
274
236
|
|
|
275
|
-
|
|
276
|
-
// Mock the isApprovedForAll call
|
|
277
|
-
;(provider as any).call.mockResolvedValue('0x1') // true
|
|
278
|
-
}
|
|
237
|
+
vi.mocked(provider.call).mockResolvedValue('0x1' as Hex.Hex) // true
|
|
279
238
|
|
|
280
|
-
const isValid = await relayer.checkPrecondition(
|
|
239
|
+
const isValid = await relayer.checkPrecondition(transactionPrecondition)
|
|
281
240
|
expect(isValid).toBe(true)
|
|
282
241
|
})
|
|
283
242
|
})
|