accounts 0.6.7 → 0.7.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/CHANGELOG.md +16 -0
- package/dist/core/ExecutionError.d.ts +25 -0
- package/dist/core/ExecutionError.d.ts.map +1 -0
- package/dist/core/ExecutionError.js +170 -0
- package/dist/core/ExecutionError.js.map +1 -0
- package/dist/core/Schema.d.ts +33 -7
- package/dist/core/Schema.d.ts.map +1 -1
- package/dist/core/zod/rpc.d.ts +14 -1
- package/dist/core/zod/rpc.d.ts.map +1 -1
- package/dist/core/zod/rpc.js +14 -1
- package/dist/core/zod/rpc.js.map +1 -1
- package/dist/server/CliAuth.d.ts +110 -43
- package/dist/server/CliAuth.d.ts.map +1 -1
- package/dist/server/CliAuth.js +243 -155
- package/dist/server/CliAuth.js.map +1 -1
- package/dist/server/Handler.d.ts +0 -1
- package/dist/server/Handler.d.ts.map +1 -1
- package/dist/server/Handler.js +0 -1
- package/dist/server/Handler.js.map +1 -1
- package/dist/server/internal/handlers/relay.d.ts +29 -12
- package/dist/server/internal/handlers/relay.d.ts.map +1 -1
- package/dist/server/internal/handlers/relay.js +180 -125
- package/dist/server/internal/handlers/relay.js.map +1 -1
- package/dist/server/internal/handlers/sponsorship.d.ts +77 -0
- package/dist/server/internal/handlers/sponsorship.d.ts.map +1 -0
- package/dist/server/internal/handlers/sponsorship.js +96 -0
- package/dist/server/internal/handlers/sponsorship.js.map +1 -0
- package/dist/server/internal/handlers/utils.d.ts +3 -1
- package/dist/server/internal/handlers/utils.d.ts.map +1 -1
- package/dist/server/internal/handlers/utils.js +15 -12
- package/dist/server/internal/handlers/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ExecutionError.test.ts +205 -0
- package/src/core/ExecutionError.ts +189 -0
- package/src/core/Provider.test.ts +4 -2
- package/src/core/zod/rpc.ts +18 -1
- package/src/server/CliAuth.test-d.ts +6 -0
- package/src/server/CliAuth.test.ts +83 -0
- package/src/server/CliAuth.ts +331 -208
- package/src/server/Handler.ts +0 -1
- package/src/server/internal/handlers/relay.test.ts +318 -108
- package/src/server/internal/handlers/relay.ts +243 -138
- package/src/server/internal/handlers/sponsorship.ts +172 -0
- package/src/server/internal/handlers/utils.ts +15 -10
- package/dist/server/internal/handlers/feePayer.d.ts +0 -73
- package/dist/server/internal/handlers/feePayer.d.ts.map +0 -1
- package/dist/server/internal/handlers/feePayer.js +0 -184
- package/dist/server/internal/handlers/feePayer.js.map +0 -1
- package/src/server/internal/handlers/feePayer.test.ts +0 -336
- package/src/server/internal/handlers/feePayer.ts +0 -271
package/src/server/Handler.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { Hono } from 'hono'
|
|
|
3
3
|
import * as RequestListener from './internal/requestListener.js'
|
|
4
4
|
|
|
5
5
|
export { codeAuth } from './internal/handlers/codeAuth.js'
|
|
6
|
-
export { feePayer } from './internal/handlers/feePayer.js'
|
|
7
6
|
export { relay } from './internal/handlers/relay.js'
|
|
8
7
|
export { webAuthn } from './internal/handlers/webAuthn.js'
|
|
9
8
|
|
|
@@ -2,6 +2,7 @@ import type { RpcRequest } from 'ox'
|
|
|
2
2
|
import { SignatureEnvelope, TxEnvelopeTempo } from 'ox/tempo'
|
|
3
3
|
import { parseUnits } from 'viem'
|
|
4
4
|
import { fillTransaction, sendTransactionSync } from 'viem/actions'
|
|
5
|
+
import { tempoModerato } from 'viem/chains'
|
|
5
6
|
import { Actions, Addresses, Capabilities, Tick, Transaction } from 'viem/tempo'
|
|
6
7
|
import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vp/test'
|
|
7
8
|
|
|
@@ -31,21 +32,23 @@ const transferCall = () =>
|
|
|
31
32
|
amount: 1n,
|
|
32
33
|
})
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
beforeAll(async () => {
|
|
36
|
+
// Fund userAccount with alphaUsd for fees + transfers.
|
|
37
|
+
const rpc = getClient()
|
|
38
|
+
await Actions.token.mintSync(rpc, {
|
|
39
|
+
account: accounts[0]!,
|
|
40
|
+
token: addresses.alphaUsd,
|
|
41
|
+
amount: parseUnits('100', 6),
|
|
42
|
+
to: userAccount.address,
|
|
43
|
+
})
|
|
44
|
+
await Actions.fee.setUserToken(rpc, { account: userAccount, token: addresses.alphaUsd })
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
describe('default', () => {
|
|
35
48
|
let client: ReturnType<typeof getClient<typeof chain>>
|
|
36
49
|
let server: Server
|
|
37
50
|
|
|
38
51
|
beforeAll(async () => {
|
|
39
|
-
// Fund userAccount with alphaUsd for fees + transfers.
|
|
40
|
-
const rpc = getClient()
|
|
41
|
-
await Actions.token.mintSync(rpc, {
|
|
42
|
-
account: accounts[0]!,
|
|
43
|
-
token: addresses.alphaUsd,
|
|
44
|
-
amount: parseUnits('100', 6),
|
|
45
|
-
to: userAccount.address,
|
|
46
|
-
})
|
|
47
|
-
await Actions.fee.setUserToken(rpc, { account: userAccount, token: addresses.alphaUsd })
|
|
48
|
-
|
|
49
52
|
server = await createServer(
|
|
50
53
|
relay({
|
|
51
54
|
chains: [chain],
|
|
@@ -95,6 +98,154 @@ describe('behavior: without feePayer', () => {
|
|
|
95
98
|
})
|
|
96
99
|
})
|
|
97
100
|
|
|
101
|
+
describe('behavior: with feePayer', () => {
|
|
102
|
+
let server: Server
|
|
103
|
+
let client: ReturnType<typeof getClient<typeof chain>>
|
|
104
|
+
let requests: RpcRequest.RpcRequest[] = []
|
|
105
|
+
|
|
106
|
+
beforeAll(async () => {
|
|
107
|
+
server = await createServer(
|
|
108
|
+
relay({
|
|
109
|
+
chains: [chain],
|
|
110
|
+
transports: { [chain.id]: http() },
|
|
111
|
+
feePayer: {
|
|
112
|
+
account: feePayerAccount,
|
|
113
|
+
name: 'Test Sponsor',
|
|
114
|
+
url: 'https://test.com',
|
|
115
|
+
},
|
|
116
|
+
onRequest: async (request) => {
|
|
117
|
+
requests.push(request)
|
|
118
|
+
},
|
|
119
|
+
}).listener,
|
|
120
|
+
)
|
|
121
|
+
client = getClient({ transport: http(server.url) })
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
afterAll(() => {
|
|
125
|
+
server.close()
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
afterEach(() => {
|
|
129
|
+
requests = []
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('default: returns sponsored tx with feePayerSignature', async () => {
|
|
133
|
+
const { transaction } = await fillTransaction(client, {
|
|
134
|
+
account: userAccount.address,
|
|
135
|
+
calls: [transferCall()],
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
expect(transaction.feePayerSignature).toBeDefined()
|
|
139
|
+
expect(requests.map(({ method }) => method)).toMatchInlineSnapshot(`
|
|
140
|
+
[
|
|
141
|
+
"eth_fillTransaction",
|
|
142
|
+
]
|
|
143
|
+
`)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
test('behavior: returns sponsor capabilities', async () => {
|
|
147
|
+
const result = await fillTransaction(client, {
|
|
148
|
+
account: userAccount.address,
|
|
149
|
+
calls: [transferCall()],
|
|
150
|
+
})
|
|
151
|
+
const meta = result.capabilities
|
|
152
|
+
|
|
153
|
+
expect(meta?.sponsored).toBe(true)
|
|
154
|
+
expect(meta?.sponsor).toMatchInlineSnapshot(`
|
|
155
|
+
{
|
|
156
|
+
"address": "${feePayerAccount.address}",
|
|
157
|
+
"name": "Test Sponsor",
|
|
158
|
+
"url": "https://test.com",
|
|
159
|
+
}
|
|
160
|
+
`)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test('behavior: sponsored tx can be signed and broadcast', async () => {
|
|
164
|
+
const { transaction } = await fillTransaction(client, {
|
|
165
|
+
account: userAccount.address,
|
|
166
|
+
calls: [transferCall()],
|
|
167
|
+
})
|
|
168
|
+
const serialized = (await Transaction.serialize(transaction as never)) as `0x76${string}`
|
|
169
|
+
const envelope = TxEnvelopeTempo.deserialize(serialized)
|
|
170
|
+
const signature = await userAccount.sign({
|
|
171
|
+
hash: TxEnvelopeTempo.getSignPayload(envelope),
|
|
172
|
+
})
|
|
173
|
+
const signed = TxEnvelopeTempo.serialize(envelope, {
|
|
174
|
+
signature: SignatureEnvelope.from(signature),
|
|
175
|
+
})
|
|
176
|
+
const receipt = (await getClient().request({
|
|
177
|
+
method: 'eth_sendRawTransactionSync' as never,
|
|
178
|
+
params: [signed],
|
|
179
|
+
})) as { feePayer?: string | undefined }
|
|
180
|
+
|
|
181
|
+
expect(receipt.feePayer).toBe(feePayerAccount.address.toLowerCase())
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test('behavior: missing from returns error capability', async () => {
|
|
185
|
+
const result = await fillTransaction(client, { calls: [transferCall()] })
|
|
186
|
+
expect(result.capabilities).toMatchInlineSnapshot(`
|
|
187
|
+
{
|
|
188
|
+
"error": {
|
|
189
|
+
"errorName": "unknown",
|
|
190
|
+
"message": "unknown account",
|
|
191
|
+
},
|
|
192
|
+
"sponsored": false,
|
|
193
|
+
}
|
|
194
|
+
`)
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('behavior: chainId path parameter', () => {
|
|
199
|
+
let server: Server
|
|
200
|
+
let client: ReturnType<typeof getClient<typeof chain>>
|
|
201
|
+
|
|
202
|
+
beforeAll(async () => {
|
|
203
|
+
server = await createServer(
|
|
204
|
+
relay({
|
|
205
|
+
chains: [chain],
|
|
206
|
+
transports: { [chain.id]: http() },
|
|
207
|
+
}).listener,
|
|
208
|
+
)
|
|
209
|
+
client = getClient({ transport: http(`${server.url}/${chain.id}`) })
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
afterAll(() => {
|
|
213
|
+
server.close()
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('default: proxies RPC methods via /:chainId path', async () => {
|
|
217
|
+
const chainId = await client.request({ method: 'eth_chainId' })
|
|
218
|
+
expect(Number(chainId)).toMatchInlineSnapshot(`${chain.id}`)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('behavior: fills transaction via /:chainId path', async () => {
|
|
222
|
+
const { transaction } = await fillTransaction(client, {
|
|
223
|
+
account: userAccount.address,
|
|
224
|
+
calls: [transferCall()],
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
expect(transaction.gas).toBeDefined()
|
|
228
|
+
expect(transaction.nonce).toBeDefined()
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
test('behavior: handles batch requests via /:chainId path', async () => {
|
|
232
|
+
const response = await fetch(`${server.url}/${chain.id}`, {
|
|
233
|
+
method: 'POST',
|
|
234
|
+
headers: { 'Content-Type': 'application/json' },
|
|
235
|
+
body: JSON.stringify([
|
|
236
|
+
{ jsonrpc: '2.0', id: 1, method: 'eth_chainId', params: [] },
|
|
237
|
+
{ jsonrpc: '2.0', id: 2, method: 'eth_chainId', params: [] },
|
|
238
|
+
]),
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
expect(response.status).toBe(200)
|
|
242
|
+
const body = (await response.json()) as { id: number; result: string }[]
|
|
243
|
+
expect(body).toHaveLength(2)
|
|
244
|
+
expect(Number(body[0]!.result)).toBe(chain.id)
|
|
245
|
+
expect(Number(body[1]!.result)).toBe(chain.id)
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
|
|
98
249
|
describe('behavior: capabilities', () => {
|
|
99
250
|
let server: Server
|
|
100
251
|
let client: ReturnType<typeof getClient<typeof chain>>
|
|
@@ -103,6 +254,7 @@ describe('behavior: capabilities', () => {
|
|
|
103
254
|
server = await createServer(
|
|
104
255
|
relay({
|
|
105
256
|
chains: [chain],
|
|
257
|
+
features: 'all',
|
|
106
258
|
transports: { [chain.id]: http() },
|
|
107
259
|
}).listener,
|
|
108
260
|
)
|
|
@@ -333,6 +485,7 @@ describe('behavior: AMM resolution', () => {
|
|
|
333
485
|
server = await createServer(
|
|
334
486
|
relay({
|
|
335
487
|
chains: [chain],
|
|
488
|
+
features: 'all',
|
|
336
489
|
transports: { [chain.id]: http() },
|
|
337
490
|
}).listener,
|
|
338
491
|
)
|
|
@@ -494,6 +647,7 @@ describe('behavior: AMM resolution', () => {
|
|
|
494
647
|
const customServer = await createServer(
|
|
495
648
|
relay({
|
|
496
649
|
chains: [chain],
|
|
650
|
+
features: 'all',
|
|
497
651
|
transports: { [chain.id]: http() },
|
|
498
652
|
autoSwap: { slippage: 0.02 },
|
|
499
653
|
}).listener,
|
|
@@ -563,112 +717,49 @@ describe('behavior: AMM resolution', () => {
|
|
|
563
717
|
const customServer = await createServer(
|
|
564
718
|
relay({
|
|
565
719
|
chains: [chain],
|
|
720
|
+
features: 'all',
|
|
566
721
|
transports: { [chain.id]: http() },
|
|
567
722
|
autoSwap: false,
|
|
568
723
|
}).listener,
|
|
569
724
|
)
|
|
570
725
|
const customClient = getClient({ transport: http(customServer.url) })
|
|
571
726
|
|
|
572
|
-
// Should
|
|
573
|
-
await
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
amount: parseUnits('5', 6),
|
|
580
|
-
}),
|
|
727
|
+
// Should return error capability instead of auto-swapping.
|
|
728
|
+
const result = await fillTransaction(customClient, {
|
|
729
|
+
account: sender.address,
|
|
730
|
+
...Actions.token.transfer.call({
|
|
731
|
+
token: base,
|
|
732
|
+
to: accounts[7]!.address,
|
|
733
|
+
amount: parseUnits('5', 6),
|
|
581
734
|
}),
|
|
582
|
-
).rejects.toThrow()
|
|
583
|
-
customServer.close()
|
|
584
|
-
})
|
|
585
|
-
})
|
|
586
|
-
|
|
587
|
-
describe('behavior: with feePayer', () => {
|
|
588
|
-
let server: Server
|
|
589
|
-
let client: ReturnType<typeof getClient<typeof chain>>
|
|
590
|
-
let requests: RpcRequest.RpcRequest[] = []
|
|
591
|
-
|
|
592
|
-
beforeAll(async () => {
|
|
593
|
-
server = await createServer(
|
|
594
|
-
relay({
|
|
595
|
-
chains: [chain],
|
|
596
|
-
transports: { [chain.id]: http() },
|
|
597
|
-
feePayer: {
|
|
598
|
-
account: feePayerAccount,
|
|
599
|
-
name: 'Test Sponsor',
|
|
600
|
-
url: 'https://test.com',
|
|
601
|
-
},
|
|
602
|
-
onRequest: async (request) => {
|
|
603
|
-
requests.push(request)
|
|
604
|
-
},
|
|
605
|
-
}).listener,
|
|
606
|
-
)
|
|
607
|
-
client = getClient({ transport: http(server.url) })
|
|
608
|
-
})
|
|
609
|
-
|
|
610
|
-
afterAll(() => {
|
|
611
|
-
server.close()
|
|
612
|
-
})
|
|
613
|
-
|
|
614
|
-
afterEach(() => {
|
|
615
|
-
requests = []
|
|
616
|
-
})
|
|
617
|
-
|
|
618
|
-
test('default: returns sponsored tx with feePayerSignature', async () => {
|
|
619
|
-
const { transaction } = await fillTransaction(client, {
|
|
620
|
-
account: userAccount.address,
|
|
621
|
-
calls: [transferCall()],
|
|
622
735
|
})
|
|
623
|
-
|
|
624
|
-
expect(
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
736
|
+
const error = result.capabilities?.error
|
|
737
|
+
expect({ ...error, data: undefined }).toMatchInlineSnapshot(`
|
|
738
|
+
{
|
|
739
|
+
"abiItem": {
|
|
740
|
+
"inputs": [
|
|
741
|
+
{
|
|
742
|
+
"name": "available",
|
|
743
|
+
"type": "uint256",
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
"name": "required",
|
|
747
|
+
"type": "uint256",
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
"name": "token",
|
|
751
|
+
"type": "address",
|
|
752
|
+
},
|
|
753
|
+
],
|
|
754
|
+
"name": "InsufficientBalance",
|
|
755
|
+
"type": "error",
|
|
756
|
+
},
|
|
757
|
+
"data": undefined,
|
|
758
|
+
"errorName": "InsufficientBalance",
|
|
759
|
+
"message": "Insufficient balance. Required: 5000000, available: 0.",
|
|
760
|
+
}
|
|
629
761
|
`)
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
test('behavior: returns sponsor capabilities', async () => {
|
|
633
|
-
const result = await fillTransaction(client, {
|
|
634
|
-
account: userAccount.address,
|
|
635
|
-
calls: [transferCall()],
|
|
636
|
-
})
|
|
637
|
-
const meta = result.capabilities
|
|
638
|
-
|
|
639
|
-
expect(meta?.sponsored).toBe(true)
|
|
640
|
-
expect(meta?.sponsor).toMatchInlineSnapshot(`
|
|
641
|
-
{
|
|
642
|
-
"address": "${feePayerAccount.address}",
|
|
643
|
-
"name": "Test Sponsor",
|
|
644
|
-
"url": "https://test.com",
|
|
645
|
-
}
|
|
646
|
-
`)
|
|
647
|
-
})
|
|
648
|
-
|
|
649
|
-
test('behavior: sponsored tx can be signed and broadcast', async () => {
|
|
650
|
-
const { transaction } = await fillTransaction(client, {
|
|
651
|
-
account: userAccount.address,
|
|
652
|
-
calls: [transferCall()],
|
|
653
|
-
})
|
|
654
|
-
const serialized = (await Transaction.serialize(transaction as never)) as `0x76${string}`
|
|
655
|
-
const envelope = TxEnvelopeTempo.deserialize(serialized)
|
|
656
|
-
const signature = await userAccount.sign({
|
|
657
|
-
hash: TxEnvelopeTempo.getSignPayload(envelope),
|
|
658
|
-
})
|
|
659
|
-
const signed = TxEnvelopeTempo.serialize(envelope, {
|
|
660
|
-
signature: SignatureEnvelope.from(signature),
|
|
661
|
-
})
|
|
662
|
-
const receipt = (await getClient().request({
|
|
663
|
-
method: 'eth_sendRawTransactionSync' as never,
|
|
664
|
-
params: [signed],
|
|
665
|
-
})) as { feePayer?: string | undefined }
|
|
666
|
-
|
|
667
|
-
expect(receipt.feePayer).toBe(feePayerAccount.address.toLowerCase())
|
|
668
|
-
})
|
|
669
|
-
|
|
670
|
-
test('behavior: missing from returns error', async () => {
|
|
671
|
-
await expect(fillTransaction(client, { calls: [transferCall()] })).rejects.toThrowError()
|
|
762
|
+
customServer.close()
|
|
672
763
|
})
|
|
673
764
|
})
|
|
674
765
|
|
|
@@ -781,6 +872,7 @@ describe('behavior: fee token resolution', () => {
|
|
|
781
872
|
server = await createServer(
|
|
782
873
|
relay({
|
|
783
874
|
chains: [chain],
|
|
875
|
+
features: 'all',
|
|
784
876
|
transports: { [chain.id]: http() },
|
|
785
877
|
}).listener,
|
|
786
878
|
)
|
|
@@ -854,3 +946,121 @@ describe('behavior: fee token resolution', () => {
|
|
|
854
946
|
expect(transaction.feeToken).toBeUndefined()
|
|
855
947
|
})
|
|
856
948
|
})
|
|
949
|
+
|
|
950
|
+
describe('behavior: error capabilities', () => {
|
|
951
|
+
let server: Server
|
|
952
|
+
let client: ReturnType<typeof getClient<typeof chain>>
|
|
953
|
+
|
|
954
|
+
beforeAll(async () => {
|
|
955
|
+
server = await createServer(
|
|
956
|
+
relay({
|
|
957
|
+
chains: [tempoModerato],
|
|
958
|
+
features: 'all',
|
|
959
|
+
transports: { [tempoModerato.id]: http('https://rpc.moderato.tempo.xyz') },
|
|
960
|
+
}).listener,
|
|
961
|
+
)
|
|
962
|
+
client = getClient({ chain: tempoModerato, transport: http(server.url) })
|
|
963
|
+
})
|
|
964
|
+
|
|
965
|
+
afterAll(() => {
|
|
966
|
+
server.close()
|
|
967
|
+
})
|
|
968
|
+
|
|
969
|
+
test('behavior: returns requireFunds on InsufficientBalance', async () => {
|
|
970
|
+
const sender = accounts[10]!
|
|
971
|
+
|
|
972
|
+
const result = await fillTransaction(client, {
|
|
973
|
+
account: sender.address,
|
|
974
|
+
calls: [
|
|
975
|
+
Actions.token.transfer.call({
|
|
976
|
+
token: addresses.alphaUsd,
|
|
977
|
+
to: recipient.address,
|
|
978
|
+
amount: parseUnits('100', 6),
|
|
979
|
+
}),
|
|
980
|
+
],
|
|
981
|
+
})
|
|
982
|
+
|
|
983
|
+
expect(result.capabilities).toMatchInlineSnapshot(`
|
|
984
|
+
{
|
|
985
|
+
"balanceDiffs": {
|
|
986
|
+
"0x0eB552e73e6f8E0922749e0fB08af2a71ECb2b7F": [
|
|
987
|
+
{
|
|
988
|
+
"address": "0x20c0000000000000000000000000000000000001",
|
|
989
|
+
"decimals": 6,
|
|
990
|
+
"direction": "outgoing",
|
|
991
|
+
"formatted": "100",
|
|
992
|
+
"name": "AlphaUSD",
|
|
993
|
+
"recipients": [
|
|
994
|
+
"0xAF4311d557fBC876059e39306ec1f3343753df29",
|
|
995
|
+
],
|
|
996
|
+
"symbol": "AlphaUSD",
|
|
997
|
+
"value": "0x5f5e100",
|
|
998
|
+
},
|
|
999
|
+
],
|
|
1000
|
+
},
|
|
1001
|
+
"error": {
|
|
1002
|
+
"abiItem": {
|
|
1003
|
+
"inputs": [
|
|
1004
|
+
{
|
|
1005
|
+
"name": "available",
|
|
1006
|
+
"type": "uint256",
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
"name": "required",
|
|
1010
|
+
"type": "uint256",
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
"name": "token",
|
|
1014
|
+
"type": "address",
|
|
1015
|
+
},
|
|
1016
|
+
],
|
|
1017
|
+
"name": "InsufficientBalance",
|
|
1018
|
+
"type": "error",
|
|
1019
|
+
},
|
|
1020
|
+
"data": "0x832f98b500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000020c0000000000000000000000000000000000001",
|
|
1021
|
+
"errorName": "InsufficientBalance",
|
|
1022
|
+
"message": "Insufficient balance. Required: 100000000, available: 0.",
|
|
1023
|
+
},
|
|
1024
|
+
"requireFunds": {
|
|
1025
|
+
"amount": "0x5f5e100",
|
|
1026
|
+
"decimals": 6,
|
|
1027
|
+
"formatted": "100",
|
|
1028
|
+
"symbol": "AlphaUSD",
|
|
1029
|
+
"token": "0x20C0000000000000000000000000000000000001",
|
|
1030
|
+
},
|
|
1031
|
+
"sponsored": false,
|
|
1032
|
+
}
|
|
1033
|
+
`)
|
|
1034
|
+
})
|
|
1035
|
+
|
|
1036
|
+
test('behavior: returns error capability on generic revert', async () => {
|
|
1037
|
+
const sender = accounts[10]!
|
|
1038
|
+
|
|
1039
|
+
const result = await fillTransaction(client, {
|
|
1040
|
+
account: sender.address,
|
|
1041
|
+
calls: [
|
|
1042
|
+
Actions.token.grantRoles.call({
|
|
1043
|
+
token: addresses.alphaUsd,
|
|
1044
|
+
role: 'issuer',
|
|
1045
|
+
to: sender.address,
|
|
1046
|
+
}),
|
|
1047
|
+
],
|
|
1048
|
+
})
|
|
1049
|
+
|
|
1050
|
+
expect(result.capabilities).toMatchInlineSnapshot(`
|
|
1051
|
+
{
|
|
1052
|
+
"error": {
|
|
1053
|
+
"abiItem": {
|
|
1054
|
+
"inputs": [],
|
|
1055
|
+
"name": "Unauthorized",
|
|
1056
|
+
"type": "error",
|
|
1057
|
+
},
|
|
1058
|
+
"data": "0x82b42900",
|
|
1059
|
+
"errorName": "Unauthorized",
|
|
1060
|
+
"message": "Unauthorized.",
|
|
1061
|
+
},
|
|
1062
|
+
"sponsored": false,
|
|
1063
|
+
}
|
|
1064
|
+
`)
|
|
1065
|
+
})
|
|
1066
|
+
})
|