stxer 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -29
- package/dist/{batch-api.d.ts → BatchAPI.d.ts} +0 -9
- package/dist/BatchProcessor.d.ts +47 -0
- package/dist/clarity-api.d.ts +27 -0
- package/dist/index.d.ts +2 -1
- package/dist/stxer.cjs.development.js +316 -57
- package/dist/stxer.cjs.development.js.map +1 -1
- package/dist/stxer.cjs.production.min.js +1 -1
- package/dist/stxer.cjs.production.min.js.map +1 -1
- package/dist/stxer.esm.js +316 -59
- package/dist/stxer.esm.js.map +1 -1
- package/package.json +6 -4
- package/src/{batch-api.ts → BatchAPI.ts} +1 -54
- package/src/BatchProcessor.ts +172 -0
- package/src/clarity-api.ts +186 -0
- package/src/index.ts +2 -1
- package/src/sample/read.ts +177 -120
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClarityType,
|
|
3
|
+
type ClarityValue,
|
|
4
|
+
type OptionalCV,
|
|
5
|
+
} from '@stacks/transactions';
|
|
6
|
+
import type {
|
|
7
|
+
ClarityAbiFunction,
|
|
8
|
+
ClarityAbiMap,
|
|
9
|
+
ClarityAbiVariable,
|
|
10
|
+
TContractPrincipal,
|
|
11
|
+
TPrincipal,
|
|
12
|
+
} from 'clarity-abi';
|
|
13
|
+
import { decodeAbi, encodeAbi } from 'ts-clarity';
|
|
14
|
+
import type {
|
|
15
|
+
InferReadonlyCallParameterType,
|
|
16
|
+
InferReadonlyCallResultType,
|
|
17
|
+
InferMapValueType,
|
|
18
|
+
InferReadMapParameterType,
|
|
19
|
+
InferReadVariableParameterType,
|
|
20
|
+
InferVariableType,
|
|
21
|
+
} from 'ts-clarity';
|
|
22
|
+
import { BatchProcessor } from './BatchProcessor';
|
|
23
|
+
|
|
24
|
+
// Shared processor instance with default settings
|
|
25
|
+
const defaultProcessor = new BatchProcessor({
|
|
26
|
+
batchDelayMs: 100,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export type ReadonlyCallRuntimeOptions = {
|
|
30
|
+
sender?: TPrincipal;
|
|
31
|
+
contract: TContractPrincipal;
|
|
32
|
+
stacksEndpoint?: string;
|
|
33
|
+
indexBlockHash?: string;
|
|
34
|
+
batchProcessor?: BatchProcessor;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type ReadMapRuntimeParameters = {
|
|
38
|
+
contract: TContractPrincipal;
|
|
39
|
+
stacksEndpoint?: string;
|
|
40
|
+
proof?: boolean;
|
|
41
|
+
indexBlockHash?: string;
|
|
42
|
+
batchProcessor?: BatchProcessor;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type ReadVariableRuntimeParameterType = {
|
|
46
|
+
contract: TContractPrincipal;
|
|
47
|
+
stacksEndpoint?: string;
|
|
48
|
+
proof?: boolean;
|
|
49
|
+
indexBlockHash?: string;
|
|
50
|
+
batchProcessor?: BatchProcessor;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export async function callReadonly<
|
|
54
|
+
Functions extends readonly ClarityAbiFunction[] | readonly unknown[],
|
|
55
|
+
FunctionName extends string,
|
|
56
|
+
>(
|
|
57
|
+
params: InferReadonlyCallParameterType<Functions, FunctionName> &
|
|
58
|
+
ReadonlyCallRuntimeOptions,
|
|
59
|
+
): Promise<InferReadonlyCallResultType<Functions, FunctionName>> {
|
|
60
|
+
const processor = params.batchProcessor ?? defaultProcessor;
|
|
61
|
+
const [deployer, contractName] = params.contract.split('.', 2);
|
|
62
|
+
const fn = String(params.functionName);
|
|
63
|
+
|
|
64
|
+
const functionDef = (params.abi as readonly ClarityAbiFunction[]).find(
|
|
65
|
+
(def) => def.name === params.functionName,
|
|
66
|
+
);
|
|
67
|
+
if (!functionDef) {
|
|
68
|
+
throw new Error(`failed to find function definition for ${params.functionName}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const argsKV = (params as unknown as { args: Record<string, unknown> }).args;
|
|
72
|
+
const args: ClarityValue[] = [];
|
|
73
|
+
for (const argDef of functionDef.args) {
|
|
74
|
+
args.push(encodeAbi(argDef.type, argsKV[argDef.name]));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
processor.enqueue({
|
|
79
|
+
request: {
|
|
80
|
+
mode: 'readonly',
|
|
81
|
+
contractAddress: deployer,
|
|
82
|
+
contractName: contractName,
|
|
83
|
+
functionName: fn,
|
|
84
|
+
functionArgs: args,
|
|
85
|
+
},
|
|
86
|
+
tip: params.indexBlockHash,
|
|
87
|
+
resolve: (result: ClarityValue | OptionalCV) => {
|
|
88
|
+
try {
|
|
89
|
+
const decoded = decodeAbi(functionDef.outputs.type, result);
|
|
90
|
+
resolve(decoded as InferReadonlyCallResultType<Functions, FunctionName>);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
reject(error);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
reject,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function readMap<
|
|
101
|
+
Maps extends readonly ClarityAbiMap[] | readonly unknown[] = readonly ClarityAbiMap[],
|
|
102
|
+
MapName extends string = string,
|
|
103
|
+
>(
|
|
104
|
+
params: InferReadMapParameterType<Maps, MapName> & ReadMapRuntimeParameters,
|
|
105
|
+
): Promise<InferMapValueType<Maps, MapName> | null> {
|
|
106
|
+
const processor = params.batchProcessor ?? defaultProcessor;
|
|
107
|
+
const [deployer, contractName] = params.contract.split('.', 2);
|
|
108
|
+
|
|
109
|
+
const mapDef = (params.abi as readonly ClarityAbiMap[]).find(
|
|
110
|
+
(m) => m.name === params.mapName,
|
|
111
|
+
);
|
|
112
|
+
if (!mapDef) {
|
|
113
|
+
throw new Error(`failed to find map definition for ${params.mapName}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const key: ClarityValue = encodeAbi(mapDef.key, params.key);
|
|
117
|
+
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
processor.enqueue({
|
|
120
|
+
request: {
|
|
121
|
+
mode: 'mapEntry',
|
|
122
|
+
contractAddress: deployer,
|
|
123
|
+
contractName: contractName,
|
|
124
|
+
mapName: params.mapName,
|
|
125
|
+
mapKey: key,
|
|
126
|
+
},
|
|
127
|
+
tip: params.indexBlockHash,
|
|
128
|
+
resolve: (result: ClarityValue | OptionalCV) => {
|
|
129
|
+
try {
|
|
130
|
+
if (result.type === ClarityType.OptionalNone) {
|
|
131
|
+
resolve(null);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (result.type !== ClarityType.OptionalSome) {
|
|
135
|
+
throw new Error(`unexpected map value: ${result}`);
|
|
136
|
+
}
|
|
137
|
+
const someCV = result as { type: ClarityType.OptionalSome; value: ClarityValue };
|
|
138
|
+
const decoded = decodeAbi(mapDef.value, someCV.value);
|
|
139
|
+
resolve(decoded as InferMapValueType<Maps, MapName>);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
reject(error);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
reject,
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function readVariable<
|
|
150
|
+
Variables extends readonly ClarityAbiVariable[] | readonly unknown[] = readonly ClarityAbiVariable[],
|
|
151
|
+
VariableName extends string = string,
|
|
152
|
+
>(
|
|
153
|
+
params: InferReadVariableParameterType<Variables, VariableName> &
|
|
154
|
+
ReadVariableRuntimeParameterType,
|
|
155
|
+
): Promise<InferVariableType<Variables, VariableName>> {
|
|
156
|
+
const processor = params.batchProcessor ?? defaultProcessor;
|
|
157
|
+
const [deployer, contractName] = params.contract.split('.', 2);
|
|
158
|
+
|
|
159
|
+
const varDef = (params.abi as readonly ClarityAbiVariable[]).find(
|
|
160
|
+
(def) => def.name === params.variableName,
|
|
161
|
+
);
|
|
162
|
+
if (!varDef) {
|
|
163
|
+
throw new Error(`failed to find variable definition for ${params.variableName}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return new Promise((resolve, reject) => {
|
|
167
|
+
processor.enqueue({
|
|
168
|
+
request: {
|
|
169
|
+
mode: 'variable',
|
|
170
|
+
contractAddress: deployer,
|
|
171
|
+
contractName: contractName,
|
|
172
|
+
variableName: params.variableName,
|
|
173
|
+
},
|
|
174
|
+
tip: params.indexBlockHash,
|
|
175
|
+
resolve: (result: ClarityValue | OptionalCV) => {
|
|
176
|
+
try {
|
|
177
|
+
const decoded = decodeAbi(varDef.type, result);
|
|
178
|
+
resolve(decoded as InferVariableType<Variables, VariableName>);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
reject(error);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
reject,
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
package/src/index.ts
CHANGED
package/src/sample/read.ts
CHANGED
|
@@ -1,127 +1,184 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
),
|
|
51
|
-
factor: uintCV(1e8),
|
|
52
|
-
}),
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
contract: contractPrincipalCV(
|
|
56
|
-
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
|
57
|
-
'univ2-core'
|
|
2
|
+
contractPrincipalCV,
|
|
3
|
+
principalCV,
|
|
4
|
+
tupleCV,
|
|
5
|
+
uintCV,
|
|
6
|
+
} from '@stacks/transactions';
|
|
7
|
+
import { SIP010TraitABI } from 'clarity-abi/abis'
|
|
8
|
+
import { batchRead } from '../BatchAPI';
|
|
9
|
+
import { BatchProcessor } from '../BatchProcessor';
|
|
10
|
+
import { callReadonly, readMap, readVariable } from '../clarity-api';
|
|
11
|
+
import { unwrapResponse } from 'ts-clarity';
|
|
12
|
+
|
|
13
|
+
async function batchReadsExample() {
|
|
14
|
+
const rs = await batchRead({
|
|
15
|
+
// index_block_hash:
|
|
16
|
+
// 'ce04817b9c6d90814ff9c06228d3a07d64335b1d9b01a233456fc304e34f7c0e', // block 373499
|
|
17
|
+
variables: [
|
|
18
|
+
{
|
|
19
|
+
contract: contractPrincipalCV(
|
|
20
|
+
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
|
21
|
+
'liquidity-token-v5kbe3oqvac'
|
|
22
|
+
),
|
|
23
|
+
variableName: 'balance-x',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
contract: contractPrincipalCV(
|
|
27
|
+
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
|
28
|
+
'liquidity-token-v5kbe3oqvac'
|
|
29
|
+
),
|
|
30
|
+
variableName: 'balance-y',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
contract: contractPrincipalCV(
|
|
34
|
+
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
|
35
|
+
'liquidity-token-v5kbe3oqvac'
|
|
36
|
+
),
|
|
37
|
+
variableName: 'something-not-exists',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
maps: [
|
|
41
|
+
{
|
|
42
|
+
contract: contractPrincipalCV(
|
|
43
|
+
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM',
|
|
44
|
+
'amm-registry-v2-01'
|
|
45
|
+
),
|
|
46
|
+
mapName: 'pools-data-map',
|
|
47
|
+
mapKey: tupleCV({
|
|
48
|
+
'token-x': principalCV(
|
|
49
|
+
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-wstx-v2'
|
|
58
50
|
),
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
contract: contractPrincipalCV(
|
|
64
|
-
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
|
65
|
-
'contract-not-exists'
|
|
51
|
+
'token-y': principalCV(
|
|
52
|
+
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex'
|
|
66
53
|
),
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
factor: uintCV(1e8),
|
|
55
|
+
}),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
contract: contractPrincipalCV(
|
|
59
|
+
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
|
60
|
+
'univ2-core'
|
|
61
|
+
),
|
|
62
|
+
mapName: 'pools',
|
|
63
|
+
mapKey: uintCV(1),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
contract: contractPrincipalCV(
|
|
67
|
+
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
|
68
|
+
'contract-not-exists'
|
|
69
|
+
),
|
|
70
|
+
mapName: 'pools',
|
|
71
|
+
mapKey: uintCV(1),
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
console.log(rs);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function batchQueueProcessorExample() {
|
|
79
|
+
const processor = new BatchProcessor({
|
|
80
|
+
stxerAPIEndpoint: 'https://api.stxer.xyz',
|
|
81
|
+
batchDelayMs: 1000,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
const promiseA = new Promise((resolve, reject) => {
|
|
86
|
+
processor.enqueue({
|
|
87
|
+
request: {
|
|
88
|
+
mode: 'variable',
|
|
89
|
+
contractAddress: 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
|
90
|
+
contractName: 'liquidity-token-v5kbe3oqvac',
|
|
91
|
+
variableName: 'balance-x',
|
|
92
|
+
},
|
|
93
|
+
resolve: resolve,
|
|
94
|
+
reject: reject,
|
|
71
95
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
'
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const promiseB = new Promise((resolve, reject) => {
|
|
99
|
+
processor.enqueue({
|
|
100
|
+
request: {
|
|
101
|
+
mode: 'variable',
|
|
102
|
+
contractAddress: 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
|
103
|
+
contractName: 'liquidity-token-v5kbe3oqvac',
|
|
104
|
+
variableName: 'balance-y',
|
|
105
|
+
},
|
|
106
|
+
resolve: resolve,
|
|
107
|
+
reject: reject,
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const result = await Promise.all([promiseA, promiseB]);
|
|
112
|
+
console.log(result);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// https://explorer.hiro.so/txid/SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.trait-sip-010
|
|
116
|
+
const sip010 = {
|
|
117
|
+
functions: [
|
|
118
|
+
{
|
|
119
|
+
name: 'get-balance',
|
|
120
|
+
access: 'read_only',
|
|
121
|
+
args: [
|
|
98
122
|
{
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
'sbtc-token'
|
|
102
|
-
),
|
|
103
|
-
functionName: 'function-not-exists',
|
|
104
|
-
functionArgs: [],
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
contract: contractPrincipalCV(
|
|
108
|
-
'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4',
|
|
109
|
-
'sbtc-token'
|
|
110
|
-
),
|
|
111
|
-
functionName: 'get-balance',
|
|
112
|
-
functionArgs: [stringAsciiCV('invalid-args')],
|
|
123
|
+
name: 'who',
|
|
124
|
+
type: 'principal',
|
|
113
125
|
},
|
|
114
126
|
],
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
outputs: {
|
|
128
|
+
type: {
|
|
129
|
+
response: {
|
|
130
|
+
ok: 'uint128',
|
|
131
|
+
error: 'none',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
variables: [],
|
|
138
|
+
maps: [],
|
|
139
|
+
fungible_tokens: [],
|
|
140
|
+
non_fungible_tokens: [],
|
|
141
|
+
epoch: 'Epoch2_05',
|
|
142
|
+
clarity_version: 'Clarity1',
|
|
143
|
+
} as const;
|
|
144
|
+
|
|
145
|
+
async function batchSip010Example() {
|
|
146
|
+
const supply = callReadonly({
|
|
147
|
+
abi: SIP010TraitABI.functions,
|
|
148
|
+
functionName: 'get-total-supply',
|
|
149
|
+
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
|
150
|
+
}).then(unwrapResponse)
|
|
151
|
+
const balance = callReadonly({
|
|
152
|
+
abi: SIP010TraitABI.functions,
|
|
153
|
+
functionName: 'get-balance',
|
|
154
|
+
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
|
155
|
+
args: {
|
|
156
|
+
who: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
|
157
|
+
},
|
|
158
|
+
}).then(unwrapResponse)
|
|
159
|
+
const paused = readVariable({
|
|
160
|
+
abi: [{ name: 'paused', type: 'bool', access: 'variable' },],
|
|
161
|
+
variableName: 'paused',
|
|
162
|
+
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
|
163
|
+
});
|
|
164
|
+
const approved = readMap({
|
|
165
|
+
abi: [
|
|
166
|
+
{ key: 'principal', name: 'approved-tokens', value: 'bool' },
|
|
167
|
+
],
|
|
168
|
+
mapName: 'approved-tokens',
|
|
169
|
+
key: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
|
170
|
+
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
|
171
|
+
})
|
|
172
|
+
const result = await Promise.all([supply, balance, paused, approved]);
|
|
173
|
+
console.log(result);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function main() {
|
|
177
|
+
await batchReadsExample();
|
|
178
|
+
await batchQueueProcessorExample();
|
|
179
|
+
await batchSip010Example();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (require.main === module) {
|
|
183
|
+
main().catch(console.error);
|
|
184
|
+
}
|