@thalalabs/surf 0.0.1
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/LICENSE +21 -0
- package/README.md +196 -0
- package/build/cjs/core/Client.js +80 -0
- package/build/cjs/core/Client.js.map +1 -0
- package/build/cjs/core/WalletClient.js +52 -0
- package/build/cjs/core/WalletClient.js.map +1 -0
- package/build/cjs/core/createEntryPayload.js +91 -0
- package/build/cjs/core/createEntryPayload.js.map +1 -0
- package/build/cjs/core/createViewPayload.js +78 -0
- package/build/cjs/core/createViewPayload.js.map +1 -0
- package/build/cjs/core/index.js +13 -0
- package/build/cjs/core/index.js.map +1 -0
- package/build/cjs/ensureTypes.js +40 -0
- package/build/cjs/ensureTypes.js.map +1 -0
- package/build/cjs/hooks/index.js +8 -0
- package/build/cjs/hooks/index.js.map +1 -0
- package/build/cjs/hooks/useSubmitTransaction.js +88 -0
- package/build/cjs/hooks/useSubmitTransaction.js.map +1 -0
- package/build/cjs/hooks/useWalletClient.js +14 -0
- package/build/cjs/hooks/useWalletClient.js.map +1 -0
- package/build/cjs/index.js +8 -0
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/package.json +1 -0
- package/build/cjs/types/abi.js +3 -0
- package/build/cjs/types/abi.js.map +1 -0
- package/build/cjs/types/abiClient.js +3 -0
- package/build/cjs/types/abiClient.js.map +1 -0
- package/build/cjs/types/client.js +3 -0
- package/build/cjs/types/client.js.map +1 -0
- package/build/cjs/types/common.js +3 -0
- package/build/cjs/types/common.js.map +1 -0
- package/build/cjs/types/index.js +3 -0
- package/build/cjs/types/index.js.map +1 -0
- package/build/cjs/types/walletClient.js +3 -0
- package/build/cjs/types/walletClient.js.map +1 -0
- package/build/esm/core/Client.js +75 -0
- package/build/esm/core/Client.js.map +1 -0
- package/build/esm/core/WalletClient.js +48 -0
- package/build/esm/core/WalletClient.js.map +1 -0
- package/build/esm/core/createEntryPayload.js +87 -0
- package/build/esm/core/createEntryPayload.js.map +1 -0
- package/build/esm/core/createViewPayload.js +74 -0
- package/build/esm/core/createViewPayload.js.map +1 -0
- package/build/esm/core/index.js +5 -0
- package/build/esm/core/index.js.map +1 -0
- package/build/esm/ensureTypes.js +34 -0
- package/build/esm/ensureTypes.js.map +1 -0
- package/build/esm/hooks/index.js +3 -0
- package/build/esm/hooks/index.js.map +1 -0
- package/build/esm/hooks/useSubmitTransaction.js +84 -0
- package/build/esm/hooks/useSubmitTransaction.js.map +1 -0
- package/build/esm/hooks/useWalletClient.js +10 -0
- package/build/esm/hooks/useWalletClient.js.map +1 -0
- package/build/esm/index.js +2 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/package.json +1 -0
- package/build/esm/types/abi.js +2 -0
- package/build/esm/types/abi.js.map +1 -0
- package/build/esm/types/abiClient.js +2 -0
- package/build/esm/types/abiClient.js.map +1 -0
- package/build/esm/types/client.js +2 -0
- package/build/esm/types/client.js.map +1 -0
- package/build/esm/types/common.js +2 -0
- package/build/esm/types/common.js.map +1 -0
- package/build/esm/types/index.js +2 -0
- package/build/esm/types/index.js.map +1 -0
- package/build/esm/types/walletClient.js +2 -0
- package/build/esm/types/walletClient.js.map +1 -0
- package/build/types/core/Client.d.ts +20 -0
- package/build/types/core/Client.d.ts.map +1 -0
- package/build/types/core/WalletClient.d.ts +17 -0
- package/build/types/core/WalletClient.d.ts.map +1 -0
- package/build/types/core/createEntryPayload.d.ts +4 -0
- package/build/types/core/createEntryPayload.d.ts.map +1 -0
- package/build/types/core/createViewPayload.d.ts +4 -0
- package/build/types/core/createViewPayload.d.ts.map +1 -0
- package/build/types/core/index.d.ts +5 -0
- package/build/types/core/index.d.ts.map +1 -0
- package/build/types/ensureTypes.d.ts +4 -0
- package/build/types/ensureTypes.d.ts.map +1 -0
- package/build/types/hooks/index.d.ts +3 -0
- package/build/types/hooks/index.d.ts.map +1 -0
- package/build/types/hooks/useSubmitTransaction.d.ts +19 -0
- package/build/types/hooks/useSubmitTransaction.d.ts.map +1 -0
- package/build/types/hooks/useWalletClient.d.ts +8 -0
- package/build/types/hooks/useWalletClient.d.ts.map +1 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/types/abi.d.ts +31 -0
- package/build/types/types/abi.d.ts.map +1 -0
- package/build/types/types/abiClient.d.ts +18 -0
- package/build/types/types/abiClient.d.ts.map +1 -0
- package/build/types/types/client.d.ts +24 -0
- package/build/types/types/client.d.ts.map +1 -0
- package/build/types/types/common.d.ts +60 -0
- package/build/types/types/common.d.ts.map +1 -0
- package/build/types/types/index.d.ts +5 -0
- package/build/types/types/index.d.ts.map +1 -0
- package/build/types/types/walletClient.d.ts +9 -0
- package/build/types/types/walletClient.d.ts.map +1 -0
- package/package.json +78 -0
- package/src/core/Client.ts +120 -0
- package/src/core/WalletClient.ts +64 -0
- package/src/core/__tests__/createEntryPayload.test.ts +262 -0
- package/src/core/__tests__/createViewPayload.test.ts +297 -0
- package/src/core/__tests__/submitTransaction.test.ts +112 -0
- package/src/core/__tests__/useABI.test.ts +139 -0
- package/src/core/__tests__/view.test.ts +145 -0
- package/src/core/createEntryPayload.ts +128 -0
- package/src/core/createViewPayload.ts +100 -0
- package/src/core/index.ts +4 -0
- package/src/ensureTypes.ts +42 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useSubmitTransaction.ts +117 -0
- package/src/hooks/useWalletClient.ts +10 -0
- package/src/index.ts +10 -0
- package/src/types/abi.ts +35 -0
- package/src/types/abiClient.ts +19 -0
- package/src/types/client.ts +32 -0
- package/src/types/common.ts +157 -0
- package/src/types/index.ts +9 -0
- package/src/types/walletClient.ts +10 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* These test cases depends on network, it call the real contract.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { AptosAccount } from 'aptos';
|
|
6
|
+
import { COIN_ABI } from '../../abi/coin';
|
|
7
|
+
import { createClient } from '../Client';
|
|
8
|
+
import { createEntryPayload } from '../createEntryPayload';
|
|
9
|
+
|
|
10
|
+
describe('call entry functions', () => {
|
|
11
|
+
const client = createClient({
|
|
12
|
+
nodeUrl: 'https://fullnode.testnet.aptoslabs.com/v1',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const account = new AptosAccount(
|
|
16
|
+
undefined,
|
|
17
|
+
'0xac914efd2367c7aa42c95d100592c099e487d2270bf0e0761e5fe93ff4016593',
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// Act before assertions
|
|
21
|
+
beforeAll(async () => {});
|
|
22
|
+
|
|
23
|
+
// Teardown (cleanup) after assertions
|
|
24
|
+
afterAll(() => {});
|
|
25
|
+
|
|
26
|
+
it('basic', async () => {
|
|
27
|
+
const entryPayload = createEntryPayload(COIN_ABI, {
|
|
28
|
+
function: 'transfer',
|
|
29
|
+
arguments: ['0x1', 1],
|
|
30
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const result = await client.simulateTransaction(entryPayload, { account });
|
|
34
|
+
|
|
35
|
+
expect(result.hash).toBeDefined();
|
|
36
|
+
expect((result as any).payload).toMatchInlineSnapshot(`
|
|
37
|
+
{
|
|
38
|
+
"arguments": [
|
|
39
|
+
"0x1",
|
|
40
|
+
"1",
|
|
41
|
+
],
|
|
42
|
+
"function": "0x1::coin::transfer",
|
|
43
|
+
"type": "entry_function_payload",
|
|
44
|
+
"type_arguments": [
|
|
45
|
+
"0x1::aptos_coin::AptosCoin",
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
`);
|
|
49
|
+
}, 60000);
|
|
50
|
+
|
|
51
|
+
it('vector', async () => {
|
|
52
|
+
const entryPayload = createEntryPayload(TEST_ABI, {
|
|
53
|
+
function: 'test_run_function',
|
|
54
|
+
arguments: [[1, 2, 3, 10, 20, 30]],
|
|
55
|
+
type_arguments: [],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const result = await client.simulateTransaction(entryPayload, { account });
|
|
59
|
+
|
|
60
|
+
expect(result.hash).toBeDefined();
|
|
61
|
+
expect((result as any).payload).toMatchInlineSnapshot(`
|
|
62
|
+
{
|
|
63
|
+
"arguments": [
|
|
64
|
+
"0x0102030a141e",
|
|
65
|
+
],
|
|
66
|
+
"function": "0x3d097bb505c9e5d8a96e367f371168240025877f6be8d4a88eacaafb709fe5c9::test::test_run_function",
|
|
67
|
+
"type": "entry_function_payload",
|
|
68
|
+
"type_arguments": [],
|
|
69
|
+
}
|
|
70
|
+
`);
|
|
71
|
+
}, 60000);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const TEST_ABI = {
|
|
75
|
+
address: '0x3d097bb505c9e5d8a96e367f371168240025877f6be8d4a88eacaafb709fe5c9',
|
|
76
|
+
name: 'test',
|
|
77
|
+
friends: [],
|
|
78
|
+
exposed_functions: [
|
|
79
|
+
{
|
|
80
|
+
name: 'test_run_function',
|
|
81
|
+
visibility: 'public',
|
|
82
|
+
is_entry: true,
|
|
83
|
+
is_view: false,
|
|
84
|
+
generic_type_params: [],
|
|
85
|
+
params: ['&signer', 'vector<u8>'],
|
|
86
|
+
return: [],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'test_view_function',
|
|
90
|
+
visibility: 'public',
|
|
91
|
+
is_entry: false,
|
|
92
|
+
is_view: true,
|
|
93
|
+
generic_type_params: [],
|
|
94
|
+
params: ['vector<u8>'],
|
|
95
|
+
return: ['u8'],
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
structs: [
|
|
99
|
+
{
|
|
100
|
+
name: 'RunFunctionStruct',
|
|
101
|
+
is_native: false,
|
|
102
|
+
abilities: ['key'],
|
|
103
|
+
generic_type_params: [],
|
|
104
|
+
fields: [
|
|
105
|
+
{
|
|
106
|
+
name: 'sum',
|
|
107
|
+
type: 'u8',
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
} as const;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* These test cases depends on network, it call the real contract.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { AptosAccount } from 'aptos';
|
|
6
|
+
import { COIN_ABI } from '../../abi/coin';
|
|
7
|
+
import { createClient } from '../Client';
|
|
8
|
+
|
|
9
|
+
describe('useABI', () => {
|
|
10
|
+
const client = createClient({
|
|
11
|
+
nodeUrl: 'https://fullnode.testnet.aptoslabs.com/v1',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const account = new AptosAccount(
|
|
15
|
+
undefined,
|
|
16
|
+
'0xac914efd2367c7aa42c95d100592c099e487d2270bf0e0761e5fe93ff4016593',
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Act before assertions
|
|
20
|
+
beforeAll(async () => {});
|
|
21
|
+
|
|
22
|
+
// Teardown (cleanup) after assertions
|
|
23
|
+
afterAll(() => {});
|
|
24
|
+
|
|
25
|
+
it('basic type checking', async () => {
|
|
26
|
+
// no need to run, type check only
|
|
27
|
+
() => {
|
|
28
|
+
// @ts-expect-error cannot call a function not exist
|
|
29
|
+
client.useABI(COIN_ABI).view.not_exist_func({
|
|
30
|
+
arguments: ['0x1'],
|
|
31
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// @ts-expect-error cannot call a entry function from view
|
|
35
|
+
client.useABI(COIN_ABI).view.transfer({
|
|
36
|
+
arguments: ['0x1'],
|
|
37
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// @ts-expect-error cannot call a view function from entry
|
|
41
|
+
client.useABI(COIN_ABI).entry.balance({
|
|
42
|
+
arguments: ['0x1'],
|
|
43
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
client.useABI(TEST_ABI).view.address_as_input({
|
|
47
|
+
// @ts-expect-error require two args
|
|
48
|
+
arguments: ['0x1'],
|
|
49
|
+
type_arguments: [],
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
client.useABI(TEST_ABI).view.address_as_input({
|
|
53
|
+
// @ts-expect-error require address
|
|
54
|
+
arguments: ['0x1', 1],
|
|
55
|
+
type_arguments: [],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
client.useABI(COIN_ABI).entry.transfer({
|
|
59
|
+
arguments: ['0x1', 1],
|
|
60
|
+
// @ts-expect-error require a type argument
|
|
61
|
+
type_arguments: [],
|
|
62
|
+
account
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// @ts-expect-error account is required for entry function
|
|
66
|
+
client.useABI(COIN_ABI).entry.transfer({
|
|
67
|
+
arguments: ['0x1', 1],
|
|
68
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('view', async () => {
|
|
74
|
+
const result = await client.useABI(COIN_ABI).view.name({
|
|
75
|
+
arguments: [],
|
|
76
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
77
|
+
});
|
|
78
|
+
expect(result).toMatchInlineSnapshot(`
|
|
79
|
+
[
|
|
80
|
+
"Aptos Coin",
|
|
81
|
+
]
|
|
82
|
+
`);
|
|
83
|
+
|
|
84
|
+
const result2 = await client.useABI(COIN_ABI).view.decimals({
|
|
85
|
+
arguments: [],
|
|
86
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
87
|
+
});
|
|
88
|
+
expect(result2).toMatchInlineSnapshot(`
|
|
89
|
+
[
|
|
90
|
+
8,
|
|
91
|
+
]
|
|
92
|
+
`);
|
|
93
|
+
}, 60000);
|
|
94
|
+
|
|
95
|
+
it('entry', async () => {
|
|
96
|
+
const result = await client.useABI(COIN_ABI).entry.transfer({
|
|
97
|
+
arguments: ['0x1', 1],
|
|
98
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
99
|
+
account,
|
|
100
|
+
isSimulation: true,
|
|
101
|
+
});
|
|
102
|
+
expect(result.hash).toBeDefined();
|
|
103
|
+
expect((result as any).payload).toMatchInlineSnapshot(`
|
|
104
|
+
{
|
|
105
|
+
"arguments": [
|
|
106
|
+
"0x1",
|
|
107
|
+
"1",
|
|
108
|
+
],
|
|
109
|
+
"function": "0x1::coin::transfer",
|
|
110
|
+
"type": "entry_function_payload",
|
|
111
|
+
"type_arguments": [
|
|
112
|
+
"0x1::aptos_coin::AptosCoin",
|
|
113
|
+
],
|
|
114
|
+
}
|
|
115
|
+
`);
|
|
116
|
+
}, 60000);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const TEST_ABI = {
|
|
120
|
+
"address": "0x123",
|
|
121
|
+
"name": "test",
|
|
122
|
+
"friends": [],
|
|
123
|
+
"exposed_functions": [
|
|
124
|
+
{
|
|
125
|
+
"name": "address_as_input",
|
|
126
|
+
"visibility": "public",
|
|
127
|
+
"is_entry": false,
|
|
128
|
+
"is_view": true,
|
|
129
|
+
"generic_type_params": [],
|
|
130
|
+
"params": [
|
|
131
|
+
"address",
|
|
132
|
+
"address",
|
|
133
|
+
],
|
|
134
|
+
"return": []
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
"structs": []
|
|
138
|
+
} as const;
|
|
139
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* These test cases depends on network, it call the real contract.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { COIN_ABI } from '../../abi/coin';
|
|
6
|
+
import { createClient } from '../Client';
|
|
7
|
+
import { createViewPayload } from '../createViewPayload';
|
|
8
|
+
|
|
9
|
+
describe('call view functions', () => {
|
|
10
|
+
const client = createClient({
|
|
11
|
+
nodeUrl: 'https://fullnode.testnet.aptoslabs.com/v1',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const clientMain = createClient({
|
|
15
|
+
nodeUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Act before assertions
|
|
19
|
+
beforeAll(async () => { });
|
|
20
|
+
|
|
21
|
+
// Teardown (cleanup) after assertions
|
|
22
|
+
afterAll(() => { });
|
|
23
|
+
|
|
24
|
+
it('basic', async () => {
|
|
25
|
+
const viewPayload = createViewPayload(COIN_ABI, {
|
|
26
|
+
function: 'name',
|
|
27
|
+
arguments: [],
|
|
28
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
29
|
+
});
|
|
30
|
+
const result = await client.view(viewPayload);
|
|
31
|
+
expect(result).toMatchInlineSnapshot(`
|
|
32
|
+
[
|
|
33
|
+
"Aptos Coin",
|
|
34
|
+
]
|
|
35
|
+
`);
|
|
36
|
+
|
|
37
|
+
const viewPayload2 = createViewPayload(COIN_ABI, {
|
|
38
|
+
function: 'decimals',
|
|
39
|
+
arguments: [],
|
|
40
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
41
|
+
});
|
|
42
|
+
const result2 = await client.view(viewPayload2);
|
|
43
|
+
expect(result2).toMatchInlineSnapshot(`
|
|
44
|
+
[
|
|
45
|
+
8,
|
|
46
|
+
]
|
|
47
|
+
`);
|
|
48
|
+
}, 60000);
|
|
49
|
+
|
|
50
|
+
it('vector', async () => {
|
|
51
|
+
const viewPayload = createViewPayload(TEST_ABI, {
|
|
52
|
+
function: 'test_view_function',
|
|
53
|
+
arguments: [[1, 2, 3, 10, 50]],
|
|
54
|
+
type_arguments: [],
|
|
55
|
+
});
|
|
56
|
+
const result = await client.view(viewPayload);
|
|
57
|
+
expect(result).toMatchInlineSnapshot(`
|
|
58
|
+
[
|
|
59
|
+
66,
|
|
60
|
+
]
|
|
61
|
+
`);
|
|
62
|
+
}, 60000);
|
|
63
|
+
|
|
64
|
+
it('struct', async () => {
|
|
65
|
+
const viewPayload = createViewPayload(TIERED_ORACLE_ABI, {
|
|
66
|
+
function: 'get_last_price',
|
|
67
|
+
arguments: [],
|
|
68
|
+
type_arguments: ['0x1::aptos_coin::AptosCoin'],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// The declaration in Move:
|
|
72
|
+
// struct FixedPoint64 has copy, drop, store { value: u128 }
|
|
73
|
+
const result = await clientMain.view(viewPayload);
|
|
74
|
+
expect(result.length).toBe(1);
|
|
75
|
+
expect((result[0] as any).v).toBeDefined();
|
|
76
|
+
expect(typeof (result[0] as any).v).toEqual("string");
|
|
77
|
+
}, 60000);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const TEST_ABI = {
|
|
81
|
+
address: '0x3d097bb505c9e5d8a96e367f371168240025877f6be8d4a88eacaafb709fe5c9',
|
|
82
|
+
name: 'test',
|
|
83
|
+
friends: [],
|
|
84
|
+
exposed_functions: [
|
|
85
|
+
{
|
|
86
|
+
name: 'test_run_function',
|
|
87
|
+
visibility: 'public',
|
|
88
|
+
is_entry: true,
|
|
89
|
+
is_view: false,
|
|
90
|
+
generic_type_params: [],
|
|
91
|
+
params: ['&signer', 'vector<u8>'],
|
|
92
|
+
return: [],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'test_view_function',
|
|
96
|
+
visibility: 'public',
|
|
97
|
+
is_entry: false,
|
|
98
|
+
is_view: true,
|
|
99
|
+
generic_type_params: [],
|
|
100
|
+
params: ['vector<u8>'],
|
|
101
|
+
return: ['u8'],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
structs: [
|
|
105
|
+
{
|
|
106
|
+
name: 'RunFunctionStruct',
|
|
107
|
+
is_native: false,
|
|
108
|
+
abilities: ['key'],
|
|
109
|
+
generic_type_params: [],
|
|
110
|
+
fields: [
|
|
111
|
+
{
|
|
112
|
+
name: 'sum',
|
|
113
|
+
type: 'u8',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
} as const;
|
|
119
|
+
|
|
120
|
+
const TIERED_ORACLE_ABI = {
|
|
121
|
+
"address": "0x92e95ed77b5ac815d3fbc2227e76db238339e9ca43ace45031ec2589bea5b8c",
|
|
122
|
+
"name": "tiered_oracle",
|
|
123
|
+
"friends": [
|
|
124
|
+
"0x92e95ed77b5ac815d3fbc2227e76db238339e9ca43ace45031ec2589bea5b8c::oracle"
|
|
125
|
+
],
|
|
126
|
+
"exposed_functions": [
|
|
127
|
+
{
|
|
128
|
+
"name": "get_last_price",
|
|
129
|
+
"visibility": "public",
|
|
130
|
+
"is_entry": false,
|
|
131
|
+
"is_view": true,
|
|
132
|
+
"generic_type_params": [
|
|
133
|
+
{
|
|
134
|
+
"constraints": []
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"params": [],
|
|
138
|
+
"return": [
|
|
139
|
+
"0x4dcae85fc5559071906cd5c76b7420fcbb4b0a92f00ab40ffc394aadbbff5ee9::fixed_point64::FixedPoint64"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
],
|
|
144
|
+
"structs": []
|
|
145
|
+
} as const;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { BCS, TxnBuilderTypes, TypeTagParser } from "aptos";
|
|
2
|
+
import { ensureBigInt, ensureBoolean, ensureNumber } from "../ensureTypes";
|
|
3
|
+
import { ABIRoot, EntryPayload } from "../types";
|
|
4
|
+
import { EntryFunctionName, EntryRequestPayload } from "../types/common";
|
|
5
|
+
|
|
6
|
+
export function createEntryPayload<
|
|
7
|
+
T extends ABIRoot,
|
|
8
|
+
TFuncName extends EntryFunctionName<T>
|
|
9
|
+
>(
|
|
10
|
+
abi: T,
|
|
11
|
+
payload: EntryRequestPayload<T, TFuncName>
|
|
12
|
+
): EntryPayload {
|
|
13
|
+
// TODO: remove unused variables
|
|
14
|
+
const fnAbi = abi.exposed_functions.filter(f => f.name === payload.function)[0];
|
|
15
|
+
const typeArguments: string[] = payload.type_arguments as any[];
|
|
16
|
+
const valArguments: any[] = payload.arguments as any[];
|
|
17
|
+
const abiArgs = fnAbi.params[0] === '&signer'
|
|
18
|
+
? (fnAbi.params as string[]).slice(1)
|
|
19
|
+
: fnAbi.params as string[];
|
|
20
|
+
|
|
21
|
+
// Validations
|
|
22
|
+
if (fnAbi === undefined) throw new Error(`Function ${payload.function} not found in ABI`);
|
|
23
|
+
if (abiArgs.length !== valArguments.length) throw new Error(`Function ${payload.function} expects ${fnAbi.params.length} arguments, but ${payload.arguments.length} were provided`);
|
|
24
|
+
if (fnAbi.generic_type_params.length !== typeArguments.length) throw new Error(`Function ${payload.function} expects ${fnAbi.generic_type_params.length} type arguments, but ${payload.type_arguments.length} were provided`);
|
|
25
|
+
|
|
26
|
+
// TODO: make entryRequest lazy
|
|
27
|
+
return {
|
|
28
|
+
rawPayload: {
|
|
29
|
+
...payload,
|
|
30
|
+
function: `${abi.address}::${abi.name}::${payload.function}`,
|
|
31
|
+
} as any,
|
|
32
|
+
entryRequest: TxnBuilderTypes.EntryFunction.natural(
|
|
33
|
+
`${abi.address}::${abi.name}`, // module id
|
|
34
|
+
payload.function, // function name
|
|
35
|
+
typeArguments // type arguments
|
|
36
|
+
.map((arg) => {
|
|
37
|
+
// The StructTag.fromString not support nested struct tag before aptos@1.8.4.
|
|
38
|
+
// So we use the TypeTagParser to parse the string literal into a TypeTagStruct
|
|
39
|
+
// For better compatibility.
|
|
40
|
+
// The next line of code is simpler, but not compatible with aptos below 1.8.3.
|
|
41
|
+
// return new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString(arg));
|
|
42
|
+
|
|
43
|
+
// Use the TypeTagParser to parse the string literal into a TypeTagStruct
|
|
44
|
+
const typeTagStruct = new TypeTagParser(arg).parseTypeTag() as TxnBuilderTypes.TypeTagStruct;
|
|
45
|
+
|
|
46
|
+
// Convert and return as a StructTag
|
|
47
|
+
return new TxnBuilderTypes.TypeTagStruct(new TxnBuilderTypes.StructTag(
|
|
48
|
+
typeTagStruct.value.address,
|
|
49
|
+
typeTagStruct.value.module_name,
|
|
50
|
+
typeTagStruct.value.name,
|
|
51
|
+
typeTagStruct.value.type_args,
|
|
52
|
+
));
|
|
53
|
+
}),
|
|
54
|
+
valArguments.map( // arguments
|
|
55
|
+
(arg, i) => {
|
|
56
|
+
const type = abiArgs[i];
|
|
57
|
+
const serializer = new BCS.Serializer();
|
|
58
|
+
argToBCS(type, arg, serializer);
|
|
59
|
+
return serializer.getBytes();
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
function argToBCS(type: string, arg: any, serializer: BCS.Serializer) {
|
|
68
|
+
|
|
69
|
+
const regex = /vector<([^]+)>/;
|
|
70
|
+
const match = type.match(regex);
|
|
71
|
+
if (match) { // It's vector
|
|
72
|
+
const innerType = match[1];
|
|
73
|
+
if (innerType === 'u8') {
|
|
74
|
+
if (arg instanceof Uint8Array) { // TODO: add type support for Uint8Array
|
|
75
|
+
serializer.serializeBytes(arg);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (typeof arg === "string") { // TODO: add type support for string
|
|
80
|
+
serializer.serializeStr(arg);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!Array.isArray(arg)) {
|
|
86
|
+
throw new Error("Invalid vector args.");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
serializer.serializeU32AsUleb128(arg.length);
|
|
90
|
+
|
|
91
|
+
arg.forEach((arg) => argToBCS(innerType, arg, serializer));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// TODO: it's struct
|
|
96
|
+
|
|
97
|
+
switch (type) { // It's primitive
|
|
98
|
+
case 'bool':
|
|
99
|
+
serializer.serializeBool(ensureBoolean(arg));
|
|
100
|
+
break;
|
|
101
|
+
case 'address':
|
|
102
|
+
TxnBuilderTypes.AccountAddress.fromHex(arg as string).serialize(serializer);
|
|
103
|
+
break;
|
|
104
|
+
case 'u8':
|
|
105
|
+
serializer.serializeU8(ensureNumber(arg));
|
|
106
|
+
break;
|
|
107
|
+
case 'u16':
|
|
108
|
+
serializer.serializeU16(ensureNumber(arg));
|
|
109
|
+
break;
|
|
110
|
+
case 'u32':
|
|
111
|
+
serializer.serializeU32(ensureNumber(arg));
|
|
112
|
+
break;
|
|
113
|
+
case 'u64':
|
|
114
|
+
serializer.serializeU64(ensureBigInt(arg));
|
|
115
|
+
break;
|
|
116
|
+
case 'u128':
|
|
117
|
+
serializer.serializeU128(ensureBigInt(arg));
|
|
118
|
+
break;
|
|
119
|
+
case 'u256':
|
|
120
|
+
serializer.serializeU256(ensureBigInt(arg));
|
|
121
|
+
break;
|
|
122
|
+
case '0x1::string::String':
|
|
123
|
+
serializer.serializeStr(arg as string);
|
|
124
|
+
break;
|
|
125
|
+
default:
|
|
126
|
+
throw new Error(`type "${type}" not supported`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { HexString } from "aptos";
|
|
2
|
+
import { ABIRoot, ViewPayload } from "../types";
|
|
3
|
+
import { ExtractReturnType, ViewFunctionName, ViewRequestPayload } from "../types/common";
|
|
4
|
+
import { ensureNumber } from "../ensureTypes";
|
|
5
|
+
|
|
6
|
+
// TODO: support vector<u8> input with Uint8Array
|
|
7
|
+
// TODO: support vector<u8> input with string
|
|
8
|
+
export function createViewPayload<
|
|
9
|
+
T extends ABIRoot,
|
|
10
|
+
TFuncName extends ViewFunctionName<T>
|
|
11
|
+
>(
|
|
12
|
+
abi: T,
|
|
13
|
+
payload: ViewRequestPayload<T, TFuncName>
|
|
14
|
+
):
|
|
15
|
+
ViewPayload<ExtractReturnType<T, TFuncName>> {
|
|
16
|
+
const fnAbi = abi.exposed_functions.filter(f => f.name === payload.function)[0];
|
|
17
|
+
const type_arguments: string[] = payload.type_arguments as any[];
|
|
18
|
+
const val_arguments: any[] = payload.arguments as any[];
|
|
19
|
+
|
|
20
|
+
// Validations
|
|
21
|
+
if (fnAbi === undefined) throw new Error(`Function ${payload.function} not found in ABI`);
|
|
22
|
+
if (fnAbi.params.length !== val_arguments.length) throw new Error(`Function ${payload.function} expects ${fnAbi.params.length} arguments, but ${payload.arguments.length} were provided`);
|
|
23
|
+
if (fnAbi.generic_type_params.length !== type_arguments.length) throw new Error(`Function ${payload.function} expects ${fnAbi.generic_type_params.length} type arguments, but ${payload.type_arguments.length} were provided`);
|
|
24
|
+
|
|
25
|
+
// TODO: do serialization here
|
|
26
|
+
const args = fnAbi.params.map((type, i) => {
|
|
27
|
+
if (['u8', 'u16', 'u32'].includes(type)) {
|
|
28
|
+
return ensureNumber(payload.arguments[i] as number);
|
|
29
|
+
}
|
|
30
|
+
else if (['u64', 'u128', 'u256'].includes(type)) {
|
|
31
|
+
return payload.arguments[i].toString();
|
|
32
|
+
}
|
|
33
|
+
else if (type.includes("vector")) {
|
|
34
|
+
return encodeVector(type, payload.arguments[i] as any[]);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return payload.arguments[i];
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// used to decode the return value in response
|
|
42
|
+
const decoders = fnAbi.return.map((type) => {
|
|
43
|
+
if (['u64', 'u128', 'u256'].includes(type)) {
|
|
44
|
+
return decodeBigint;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
viewRequest: {
|
|
53
|
+
function: `${abi.address}::${abi.name}::${payload.function}`,
|
|
54
|
+
arguments: args,
|
|
55
|
+
type_arguments: payload.type_arguments as string[],
|
|
56
|
+
},
|
|
57
|
+
decoders,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function decodeBigint(value: string): bigint {
|
|
62
|
+
return BigInt(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function encodeVector(type: string, value: any[]) {
|
|
66
|
+
const regex = /vector<([^]+)>/;
|
|
67
|
+
const match = type.match(regex);
|
|
68
|
+
if (!match) {
|
|
69
|
+
// Should never happen
|
|
70
|
+
throw new Error(`Unsupported type: ${type}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (match[1] === "u8") {
|
|
74
|
+
return (
|
|
75
|
+
HexString.fromUint8Array(
|
|
76
|
+
new Uint8Array(
|
|
77
|
+
value.map((v: number) => {
|
|
78
|
+
const result = ensureNumber(v);
|
|
79
|
+
if (result < 0 || result > 255)
|
|
80
|
+
throw new Error(`Invalid u8 value: ${result}`);
|
|
81
|
+
return result;
|
|
82
|
+
}),
|
|
83
|
+
),
|
|
84
|
+
) as any
|
|
85
|
+
).hexString;
|
|
86
|
+
} else if (["u16", "u32"].includes(match[1])) {
|
|
87
|
+
// TODO: Figure out how to encode
|
|
88
|
+
return value;
|
|
89
|
+
} else if (["u64", "u128", "u256"].includes(match[1])) {
|
|
90
|
+
// TODO: Figure out how to encode
|
|
91
|
+
return value.map((v: bigint) => v.toString());
|
|
92
|
+
} else if (match[1] === "bool") {
|
|
93
|
+
// TODO: Figure out how to encode
|
|
94
|
+
return value;
|
|
95
|
+
} else {
|
|
96
|
+
// 1. Address type no need to encode
|
|
97
|
+
// 2. TODO: Figure out how to encode Struct type
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function assertType(val: any, types: string[] | string, message?: string) {
|
|
2
|
+
if (!types?.includes(typeof val)) {
|
|
3
|
+
throw new Error(
|
|
4
|
+
message || `Invalid arg: ${val} type should be ${types instanceof Array ? types.join(" or ") : types}`,
|
|
5
|
+
);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ensureBoolean(val: boolean | string): boolean {
|
|
10
|
+
assertType(val, ["boolean", "string"]);
|
|
11
|
+
if (typeof val === "boolean") {
|
|
12
|
+
return val;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (val === "true") {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (val === "false") {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
throw new Error("Invalid boolean string.");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function ensureNumber(val: number | string): number {
|
|
26
|
+
assertType(val, ["number", "string"]);
|
|
27
|
+
if (typeof val === "number") {
|
|
28
|
+
return val;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const res = Number.parseInt(val, 10);
|
|
32
|
+
if (Number.isNaN(res)) {
|
|
33
|
+
throw new Error("Invalid number string.");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return res;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function ensureBigInt(val: number | bigint | string): bigint {
|
|
40
|
+
assertType(val, ["number", "bigint", "string"]);
|
|
41
|
+
return BigInt(val);
|
|
42
|
+
}
|