mirror of
https://github.com/stxer/stxer-sdk.git
synced 2026-01-12 07:23:57 +08:00
feat: support multisig address
This commit is contained in:
28
.vscode/settings.json
vendored
Normal file
28
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"editor.defaultFormatter": "biomejs.biome",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||||
|
"typescript.preferences.importModuleSpecifier": "shortest",
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.biome": "explicit"
|
||||||
|
},
|
||||||
|
"[json]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
},
|
||||||
|
"[jsonc]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
},
|
||||||
|
"[javascriptreact]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
},
|
||||||
|
"[typescriptreact]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
}
|
||||||
|
}
|
||||||
63
biome.json
Normal file
63
biome.json
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/2.2.4/schema.json",
|
||||||
|
"assist": {
|
||||||
|
"actions": {
|
||||||
|
"source": {
|
||||||
|
"organizeImports": "on"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"includes": [
|
||||||
|
"**",
|
||||||
|
"!**/coverage",
|
||||||
|
"!**/dist",
|
||||||
|
"!**/node_modules",
|
||||||
|
"!**/cache"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"formatWithErrors": false,
|
||||||
|
"indentStyle": "space",
|
||||||
|
"indentWidth": 2,
|
||||||
|
"lineWidth": 80
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"formatter": {
|
||||||
|
"quoteStyle": "single",
|
||||||
|
"trailingCommas": "all",
|
||||||
|
"semicolons": "always"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true,
|
||||||
|
"complexity": {
|
||||||
|
"noBannedTypes": "off"
|
||||||
|
},
|
||||||
|
"correctness": {
|
||||||
|
"noUnusedVariables": "error",
|
||||||
|
"noUnusedImports": "error"
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"noParameterAssign": "error",
|
||||||
|
"useAsConstAssertion": "error",
|
||||||
|
"useDefaultParameterLast": "error",
|
||||||
|
"useEnumInitializers": "error",
|
||||||
|
"useSelfClosingElements": "error",
|
||||||
|
"useSingleVarDeclarator": "error",
|
||||||
|
"noUnusedTemplateLiteral": "error",
|
||||||
|
"useNumberNamespace": "error",
|
||||||
|
"noInferrableTypes": "error",
|
||||||
|
"noUselessElse": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": false
|
||||||
|
}
|
||||||
|
}
|
||||||
29
package.json
29
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "stxer",
|
"name": "stxer",
|
||||||
"version": "0.4.2",
|
"version": "0.4.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Kyle Fang",
|
"author": "Kyle Fang",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "size-limit --why",
|
"analyze": "size-limit --why",
|
||||||
"build": "dts build",
|
"build": "dts build",
|
||||||
"lint": "dts lint",
|
"lint": "dts lint && biome check .",
|
||||||
"prepare": "dts build",
|
"prepare": "dts build",
|
||||||
"size": "size-limit",
|
"size": "size-limit",
|
||||||
"start": "dts watch",
|
"start": "dts watch",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"pre-commit": "dts lint"
|
"pre-commit": "dts lint && biome check ."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
@@ -53,22 +53,23 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@size-limit/preset-small-lib": "^11.1.5",
|
"@biomejs/biome": "^2.2.4",
|
||||||
"@tsconfig/recommended": "^1.0.7",
|
"@size-limit/preset-small-lib": "^11.2.0",
|
||||||
"@types/node": "^22.13.5",
|
"@tsconfig/recommended": "^1.0.10",
|
||||||
|
"@types/node": "^24.3.3",
|
||||||
"dts-cli": "^2.0.5",
|
"dts-cli": "^2.0.5",
|
||||||
"husky": "^9.1.6",
|
"husky": "^9.1.7",
|
||||||
"size-limit": "^11.1.5",
|
"size-limit": "^11.2.0",
|
||||||
"tslib": "^2.7.0",
|
"tslib": "^2.8.1",
|
||||||
"tsx": "^4.19.2",
|
"tsx": "^4.20.5",
|
||||||
"typescript": "^5.6.2"
|
"typescript": "^5.9.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@stacks/network": "^7.0.0",
|
"@stacks/network": "^7.2.0",
|
||||||
"@stacks/stacks-blockchain-api-types": "^7.14.1",
|
"@stacks/stacks-blockchain-api-types": "^7.14.1",
|
||||||
"@stacks/transactions": "^7.0.0",
|
"@stacks/transactions": "^7.2.0",
|
||||||
"c32check": "^2.0.0",
|
"c32check": "^2.0.0",
|
||||||
"clarity-abi": "^0.1.0",
|
"clarity-abi": "^0.1.0",
|
||||||
"ts-clarity": "^0.1.0-pre.2"
|
"ts-clarity": "^0.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4617
pnpm-lock.yaml
generated
4617
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
onlyBuiltDependencies:
|
||||||
|
- esbuild
|
||||||
@@ -59,7 +59,7 @@ function convertResults(
|
|||||||
|
|
||||||
export async function batchRead(
|
export async function batchRead(
|
||||||
reads: BatchReads,
|
reads: BatchReads,
|
||||||
options: BatchApiOptions = {}
|
options: BatchApiOptions = {},
|
||||||
): Promise<BatchReadsResult> {
|
): Promise<BatchReadsResult> {
|
||||||
const ibh =
|
const ibh =
|
||||||
reads.index_block_hash == null
|
reads.index_block_hash == null
|
||||||
@@ -77,7 +77,10 @@ export async function batchRead(
|
|||||||
|
|
||||||
if (reads.variables != null) {
|
if (reads.variables != null) {
|
||||||
for (const variable of reads.variables) {
|
for (const variable of reads.variables) {
|
||||||
payload.vars.push([serializeCV(variable.contract), variable.variableName]);
|
payload.vars.push([
|
||||||
|
serializeCV(variable.contract),
|
||||||
|
variable.variableName,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +99,7 @@ export async function batchRead(
|
|||||||
payload.readonly.push([
|
payload.readonly.push([
|
||||||
serializeCV(ro.contract),
|
serializeCV(ro.contract),
|
||||||
ro.functionName,
|
ro.functionName,
|
||||||
...ro.functionArgs.map(v => serializeCV(v)),
|
...ro.functionArgs.map((v) => serializeCV(v)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,4 +135,4 @@ export async function batchRead(
|
|||||||
maps: convertResults(rs.maps),
|
maps: convertResults(rs.maps),
|
||||||
readonly: convertResults(rs.readonly),
|
readonly: convertResults(rs.readonly),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
type ClarityValue,
|
type ClarityValue,
|
||||||
type OptionalCV,
|
|
||||||
contractPrincipalCV,
|
contractPrincipalCV,
|
||||||
|
type OptionalCV,
|
||||||
} from '@stacks/transactions';
|
} from '@stacks/transactions';
|
||||||
import { type BatchReads, batchRead } from './BatchAPI';
|
import { type BatchReads, batchRead } from './BatchAPI';
|
||||||
|
|
||||||
@@ -175,4 +175,4 @@ export class BatchProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ import type {
|
|||||||
TContractPrincipal,
|
TContractPrincipal,
|
||||||
TPrincipal,
|
TPrincipal,
|
||||||
} from 'clarity-abi';
|
} from 'clarity-abi';
|
||||||
import { decodeAbi, encodeAbi } from 'ts-clarity';
|
|
||||||
import type {
|
import type {
|
||||||
InferReadonlyCallParameterType,
|
|
||||||
InferReadonlyCallResultType,
|
|
||||||
InferMapValueType,
|
InferMapValueType,
|
||||||
InferReadMapParameterType,
|
InferReadMapParameterType,
|
||||||
|
InferReadonlyCallParameterType,
|
||||||
|
InferReadonlyCallResultType,
|
||||||
InferReadVariableParameterType,
|
InferReadVariableParameterType,
|
||||||
InferVariableType,
|
InferVariableType,
|
||||||
} from 'ts-clarity';
|
} from 'ts-clarity';
|
||||||
|
import { decodeAbi, encodeAbi } from 'ts-clarity';
|
||||||
import { BatchProcessor } from './BatchProcessor';
|
import { BatchProcessor } from './BatchProcessor';
|
||||||
|
|
||||||
// Shared processor instance with default settings
|
// Shared processor instance with default settings
|
||||||
@@ -60,14 +60,16 @@ export async function callReadonly<
|
|||||||
const processor = params.batchProcessor ?? defaultProcessor;
|
const processor = params.batchProcessor ?? defaultProcessor;
|
||||||
const [deployer, contractName] = params.contract.split('.', 2);
|
const [deployer, contractName] = params.contract.split('.', 2);
|
||||||
const fn = String(params.functionName);
|
const fn = String(params.functionName);
|
||||||
|
|
||||||
const functionDef = (params.abi as readonly ClarityAbiFunction[]).find(
|
const functionDef = (params.abi as readonly ClarityAbiFunction[]).find(
|
||||||
(def) => def.name === params.functionName,
|
(def) => def.name === params.functionName,
|
||||||
);
|
);
|
||||||
if (!functionDef) {
|
if (!functionDef) {
|
||||||
throw new Error(`failed to find function definition for ${params.functionName}`);
|
throw new Error(
|
||||||
|
`failed to find function definition for ${params.functionName}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const argsKV = (params as unknown as { args: Record<string, unknown> }).args;
|
const argsKV = (params as unknown as { args: Record<string, unknown> }).args;
|
||||||
const args: ClarityValue[] = [];
|
const args: ClarityValue[] = [];
|
||||||
for (const argDef of functionDef.args) {
|
for (const argDef of functionDef.args) {
|
||||||
@@ -87,7 +89,9 @@ export async function callReadonly<
|
|||||||
resolve: (result: ClarityValue | OptionalCV) => {
|
resolve: (result: ClarityValue | OptionalCV) => {
|
||||||
try {
|
try {
|
||||||
const decoded = decodeAbi(functionDef.outputs.type, result);
|
const decoded = decodeAbi(functionDef.outputs.type, result);
|
||||||
resolve(decoded as InferReadonlyCallResultType<Functions, FunctionName>);
|
resolve(
|
||||||
|
decoded as InferReadonlyCallResultType<Functions, FunctionName>,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
@@ -98,21 +102,23 @@ export async function callReadonly<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function readMap<
|
export async function readMap<
|
||||||
Maps extends readonly ClarityAbiMap[] | readonly unknown[] = readonly ClarityAbiMap[],
|
Maps extends
|
||||||
|
| readonly ClarityAbiMap[]
|
||||||
|
| readonly unknown[] = readonly ClarityAbiMap[],
|
||||||
MapName extends string = string,
|
MapName extends string = string,
|
||||||
>(
|
>(
|
||||||
params: InferReadMapParameterType<Maps, MapName> & ReadMapRuntimeParameters,
|
params: InferReadMapParameterType<Maps, MapName> & ReadMapRuntimeParameters,
|
||||||
): Promise<InferMapValueType<Maps, MapName> | null> {
|
): Promise<InferMapValueType<Maps, MapName> | null> {
|
||||||
const processor = params.batchProcessor ?? defaultProcessor;
|
const processor = params.batchProcessor ?? defaultProcessor;
|
||||||
const [deployer, contractName] = params.contract.split('.', 2);
|
const [deployer, contractName] = params.contract.split('.', 2);
|
||||||
|
|
||||||
const mapDef = (params.abi as readonly ClarityAbiMap[]).find(
|
const mapDef = (params.abi as readonly ClarityAbiMap[]).find(
|
||||||
(m) => m.name === params.mapName,
|
(m) => m.name === params.mapName,
|
||||||
);
|
);
|
||||||
if (!mapDef) {
|
if (!mapDef) {
|
||||||
throw new Error(`failed to find map definition for ${params.mapName}`);
|
throw new Error(`failed to find map definition for ${params.mapName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const key: ClarityValue = encodeAbi(mapDef.key, params.key);
|
const key: ClarityValue = encodeAbi(mapDef.key, params.key);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -134,7 +140,10 @@ export async function readMap<
|
|||||||
if (result.type !== ClarityType.OptionalSome) {
|
if (result.type !== ClarityType.OptionalSome) {
|
||||||
throw new Error(`unexpected map value: ${result}`);
|
throw new Error(`unexpected map value: ${result}`);
|
||||||
}
|
}
|
||||||
const someCV = result as { type: ClarityType.OptionalSome; value: ClarityValue };
|
const someCV = result as {
|
||||||
|
type: ClarityType.OptionalSome;
|
||||||
|
value: ClarityValue;
|
||||||
|
};
|
||||||
const decoded = decodeAbi(mapDef.value, someCV.value);
|
const decoded = decodeAbi(mapDef.value, someCV.value);
|
||||||
resolve(decoded as InferMapValueType<Maps, MapName>);
|
resolve(decoded as InferMapValueType<Maps, MapName>);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -147,7 +156,9 @@ export async function readMap<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function readVariable<
|
export async function readVariable<
|
||||||
Variables extends readonly ClarityAbiVariable[] | readonly unknown[] = readonly ClarityAbiVariable[],
|
Variables extends
|
||||||
|
| readonly ClarityAbiVariable[]
|
||||||
|
| readonly unknown[] = readonly ClarityAbiVariable[],
|
||||||
VariableName extends string = string,
|
VariableName extends string = string,
|
||||||
>(
|
>(
|
||||||
params: InferReadVariableParameterType<Variables, VariableName> &
|
params: InferReadVariableParameterType<Variables, VariableName> &
|
||||||
@@ -155,12 +166,14 @@ export async function readVariable<
|
|||||||
): Promise<InferVariableType<Variables, VariableName>> {
|
): Promise<InferVariableType<Variables, VariableName>> {
|
||||||
const processor = params.batchProcessor ?? defaultProcessor;
|
const processor = params.batchProcessor ?? defaultProcessor;
|
||||||
const [deployer, contractName] = params.contract.split('.', 2);
|
const [deployer, contractName] = params.contract.split('.', 2);
|
||||||
|
|
||||||
const varDef = (params.abi as readonly ClarityAbiVariable[]).find(
|
const varDef = (params.abi as readonly ClarityAbiVariable[]).find(
|
||||||
(def) => def.name === params.variableName,
|
(def) => def.name === params.variableName,
|
||||||
);
|
);
|
||||||
if (!varDef) {
|
if (!varDef) {
|
||||||
throw new Error(`failed to find variable definition for ${params.variableName}`);
|
throw new Error(
|
||||||
|
`failed to find variable definition for ${params.variableName}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -183,4 +196,4 @@ export async function readVariable<
|
|||||||
reject,
|
reject,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export * from './BatchAPI';
|
export * from './BatchAPI';
|
||||||
|
export * from './clarity-api';
|
||||||
export * from './simulation';
|
export * from './simulation';
|
||||||
export * from './clarity-api';
|
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import { uintCV } from '@stacks/transactions';
|
import { uintCV } from '@stacks/transactions';
|
||||||
import { SimulationBuilder } from '..';
|
import { SimulationBuilder } from '..';
|
||||||
|
|
||||||
const test = () => SimulationBuilder.new()
|
const sender = 'SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER';
|
||||||
.withSender('SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER')
|
|
||||||
.inlineSimulation('1ab04a8d13d72a301b77b6af9d4f612b')
|
const test = () =>
|
||||||
.addContractDeploy({
|
SimulationBuilder.new()
|
||||||
contract_name: 'test-simulation',
|
.withSender(sender)
|
||||||
source_code: `
|
.addContractDeploy({
|
||||||
|
contract_name: 'test-simulation',
|
||||||
|
source_code: `
|
||||||
;; counter example
|
;; counter example
|
||||||
(define-data-var counter uint u0)
|
(define-data-var counter uint u0)
|
||||||
|
|
||||||
@@ -23,24 +25,18 @@ const test = () => SimulationBuilder.new()
|
|||||||
(define-read-only (get-counter)
|
(define-read-only (get-counter)
|
||||||
(ok (var-get counter)))
|
(ok (var-get counter)))
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
.addEvalCode(
|
.addEvalCode(`${sender}.test-simulation`, '(get-counter)')
|
||||||
'SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER.test-simulation',
|
.addContractCall({
|
||||||
'(get-counter)'
|
contract_id: `${sender}.test-simulation`,
|
||||||
)
|
function_name: 'increment',
|
||||||
.addContractCall({
|
function_args: [uintCV(10)],
|
||||||
contract_id: 'SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER.test-simulation',
|
})
|
||||||
function_name: 'increment',
|
.addEvalCode(`${sender}.test-simulation`, '(get-counter)')
|
||||||
function_args: [uintCV(10)],
|
.run();
|
||||||
})
|
|
||||||
.addEvalCode(
|
|
||||||
'SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER.test-simulation',
|
|
||||||
'(get-counter)'
|
|
||||||
)
|
|
||||||
.run()
|
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
; (async () => {
|
(async () => {
|
||||||
await test()
|
await test();
|
||||||
})().catch(console.error);
|
})().catch(console.error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import {
|
|||||||
tupleCV,
|
tupleCV,
|
||||||
uintCV,
|
uintCV,
|
||||||
} from '@stacks/transactions';
|
} from '@stacks/transactions';
|
||||||
import { SIP010TraitABI } from 'clarity-abi/abis'
|
import { SIP010TraitABI } from 'clarity-abi/abis';
|
||||||
|
import { unwrapResponse } from 'ts-clarity';
|
||||||
import { batchRead } from '../BatchAPI';
|
import { batchRead } from '../BatchAPI';
|
||||||
import { BatchProcessor } from '../BatchProcessor';
|
import { BatchProcessor } from '../BatchProcessor';
|
||||||
import { callReadonly, readMap, readVariable } from '../clarity-api';
|
import { callReadonly, readMap, readVariable } from '../clarity-api';
|
||||||
import { unwrapResponse } from 'ts-clarity';
|
|
||||||
|
|
||||||
async function batchReadsExample() {
|
async function batchReadsExample() {
|
||||||
const rs = await batchRead({
|
const rs = await batchRead({
|
||||||
@@ -18,21 +18,21 @@ async function batchReadsExample() {
|
|||||||
{
|
{
|
||||||
contract: contractPrincipalCV(
|
contract: contractPrincipalCV(
|
||||||
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
||||||
'liquidity-token-v5kbe3oqvac'
|
'liquidity-token-v5kbe3oqvac',
|
||||||
),
|
),
|
||||||
variableName: 'balance-x',
|
variableName: 'balance-x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contract: contractPrincipalCV(
|
contract: contractPrincipalCV(
|
||||||
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
||||||
'liquidity-token-v5kbe3oqvac'
|
'liquidity-token-v5kbe3oqvac',
|
||||||
),
|
),
|
||||||
variableName: 'balance-y',
|
variableName: 'balance-y',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contract: contractPrincipalCV(
|
contract: contractPrincipalCV(
|
||||||
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
||||||
'liquidity-token-v5kbe3oqvac'
|
'liquidity-token-v5kbe3oqvac',
|
||||||
),
|
),
|
||||||
variableName: 'something-not-exists',
|
variableName: 'something-not-exists',
|
||||||
},
|
},
|
||||||
@@ -41,15 +41,15 @@ async function batchReadsExample() {
|
|||||||
{
|
{
|
||||||
contract: contractPrincipalCV(
|
contract: contractPrincipalCV(
|
||||||
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM',
|
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM',
|
||||||
'amm-registry-v2-01'
|
'amm-registry-v2-01',
|
||||||
),
|
),
|
||||||
mapName: 'pools-data-map',
|
mapName: 'pools-data-map',
|
||||||
mapKey: tupleCV({
|
mapKey: tupleCV({
|
||||||
'token-x': principalCV(
|
'token-x': principalCV(
|
||||||
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-wstx-v2'
|
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-wstx-v2',
|
||||||
),
|
),
|
||||||
'token-y': principalCV(
|
'token-y': principalCV(
|
||||||
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex'
|
'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
||||||
),
|
),
|
||||||
factor: uintCV(1e8),
|
factor: uintCV(1e8),
|
||||||
}),
|
}),
|
||||||
@@ -57,7 +57,7 @@ async function batchReadsExample() {
|
|||||||
{
|
{
|
||||||
contract: contractPrincipalCV(
|
contract: contractPrincipalCV(
|
||||||
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
||||||
'univ2-core'
|
'univ2-core',
|
||||||
),
|
),
|
||||||
mapName: 'pools',
|
mapName: 'pools',
|
||||||
mapKey: uintCV(1),
|
mapKey: uintCV(1),
|
||||||
@@ -65,7 +65,7 @@ async function batchReadsExample() {
|
|||||||
{
|
{
|
||||||
contract: contractPrincipalCV(
|
contract: contractPrincipalCV(
|
||||||
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1',
|
||||||
'contract-not-exists'
|
'contract-not-exists',
|
||||||
),
|
),
|
||||||
mapName: 'pools',
|
mapName: 'pools',
|
||||||
mapKey: uintCV(1),
|
mapKey: uintCV(1),
|
||||||
@@ -81,7 +81,6 @@ async function batchQueueProcessorExample() {
|
|||||||
batchDelayMs: 1000,
|
batchDelayMs: 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const promiseA = processor.read({
|
const promiseA = processor.read({
|
||||||
mode: 'variable',
|
mode: 'variable',
|
||||||
contractAddress: 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
contractAddress: 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275',
|
||||||
@@ -105,7 +104,7 @@ async function batchSip010Example() {
|
|||||||
abi: SIP010TraitABI.functions,
|
abi: SIP010TraitABI.functions,
|
||||||
functionName: 'get-total-supply',
|
functionName: 'get-total-supply',
|
||||||
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
||||||
}).then(unwrapResponse)
|
}).then(unwrapResponse);
|
||||||
const balance = callReadonly({
|
const balance = callReadonly({
|
||||||
abi: SIP010TraitABI.functions,
|
abi: SIP010TraitABI.functions,
|
||||||
functionName: 'get-balance',
|
functionName: 'get-balance',
|
||||||
@@ -113,20 +112,18 @@ async function batchSip010Example() {
|
|||||||
args: {
|
args: {
|
||||||
who: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
who: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
||||||
},
|
},
|
||||||
}).then(unwrapResponse)
|
}).then(unwrapResponse);
|
||||||
const paused = readVariable({
|
const paused = readVariable({
|
||||||
abi: [{ name: 'paused', type: 'bool', access: 'variable' },],
|
abi: [{ name: 'paused', type: 'bool', access: 'variable' }],
|
||||||
variableName: 'paused',
|
variableName: 'paused',
|
||||||
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
||||||
});
|
});
|
||||||
const approved = readMap({
|
const approved = readMap({
|
||||||
abi: [
|
abi: [{ key: 'principal', name: 'approved-tokens', value: 'bool' }],
|
||||||
{ key: 'principal', name: 'approved-tokens', value: 'bool' },
|
|
||||||
],
|
|
||||||
mapName: 'approved-tokens',
|
mapName: 'approved-tokens',
|
||||||
key: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
key: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-alex',
|
||||||
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
contract: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01',
|
||||||
})
|
});
|
||||||
const result = await Promise.all([supply, balance, paused, approved]);
|
const result = await Promise.all([supply, balance, paused, approved]);
|
||||||
console.log(result);
|
console.log(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,55 @@
|
|||||||
import { type AccountDataResponse, getNodeInfo, richFetch } from 'ts-clarity';
|
|
||||||
import type { Block } from '@stacks/stacks-blockchain-api-types';
|
|
||||||
import {
|
import {
|
||||||
|
AddressVersion,
|
||||||
STACKS_MAINNET,
|
STACKS_MAINNET,
|
||||||
STACKS_TESTNET,
|
STACKS_TESTNET,
|
||||||
type StacksNetworkName,
|
type StacksNetworkName,
|
||||||
} from '@stacks/network';
|
} from '@stacks/network';
|
||||||
|
import type { Block } from '@stacks/stacks-blockchain-api-types';
|
||||||
import {
|
import {
|
||||||
|
AddressHashMode,
|
||||||
|
bufferCV,
|
||||||
type ClarityValue,
|
type ClarityValue,
|
||||||
ClarityVersion,
|
ClarityVersion,
|
||||||
PostConditionMode,
|
|
||||||
type StacksTransactionWire,
|
|
||||||
bufferCV,
|
|
||||||
contractPrincipalCV,
|
contractPrincipalCV,
|
||||||
deserializeTransaction,
|
deserializeTransaction,
|
||||||
|
type MultiSigSpendingCondition,
|
||||||
makeUnsignedContractCall,
|
makeUnsignedContractCall,
|
||||||
makeUnsignedContractDeploy,
|
makeUnsignedContractDeploy,
|
||||||
makeUnsignedSTXTokenTransfer,
|
makeUnsignedSTXTokenTransfer,
|
||||||
|
PostConditionMode,
|
||||||
|
type StacksTransactionWire,
|
||||||
serializeCVBytes,
|
serializeCVBytes,
|
||||||
stringAsciiCV,
|
stringAsciiCV,
|
||||||
tupleCV,
|
tupleCV,
|
||||||
uintCV,
|
uintCV,
|
||||||
} from '@stacks/transactions';
|
} from '@stacks/transactions';
|
||||||
import { c32addressDecode } from 'c32check';
|
import { c32addressDecode } from 'c32check';
|
||||||
|
import { type AccountDataResponse, getNodeInfo, richFetch } from 'ts-clarity';
|
||||||
|
|
||||||
|
function setSender(tx: StacksTransactionWire, sender: string) {
|
||||||
|
const [addressVersion, signer] = c32addressDecode(sender);
|
||||||
|
switch (addressVersion) {
|
||||||
|
case AddressVersion.MainnetSingleSig:
|
||||||
|
case AddressVersion.TestnetSingleSig:
|
||||||
|
tx.auth.spendingCondition.hashMode = AddressHashMode.P2PKH;
|
||||||
|
tx.auth.spendingCondition.signer = signer;
|
||||||
|
break;
|
||||||
|
case AddressVersion.MainnetMultiSig:
|
||||||
|
case AddressVersion.TestnetMultiSig: {
|
||||||
|
const sc = tx.auth.spendingCondition;
|
||||||
|
tx.auth.spendingCondition = {
|
||||||
|
hashMode: AddressHashMode.P2SH,
|
||||||
|
signer,
|
||||||
|
fields: [],
|
||||||
|
signaturesRequired: 0,
|
||||||
|
nonce: sc.nonce,
|
||||||
|
fee: sc.fee,
|
||||||
|
} as MultiSigSpendingCondition;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
function runTx(tx: StacksTransactionWire) {
|
function runTx(tx: StacksTransactionWire) {
|
||||||
// type 0: run transaction
|
// type 0: run transaction
|
||||||
@@ -43,8 +71,8 @@ export function runEval({ contract_id, code }: SimulationEval) {
|
|||||||
tupleCV({
|
tupleCV({
|
||||||
contract: contractPrincipalCV(contract_address, contract_name),
|
contract: contractPrincipalCV(contract_address, contract_name),
|
||||||
code: stringAsciiCV(code),
|
code: stringAsciiCV(code),
|
||||||
})
|
}),
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -53,7 +81,7 @@ export async function runSimulation(
|
|||||||
apiEndpoint: string,
|
apiEndpoint: string,
|
||||||
block_hash: string,
|
block_hash: string,
|
||||||
block_height: number,
|
block_height: number,
|
||||||
txs: (StacksTransactionWire | SimulationEval)[]
|
txs: (StacksTransactionWire | SimulationEval)[],
|
||||||
) {
|
) {
|
||||||
// Convert 'sim-v1' to Uint8Array
|
// Convert 'sim-v1' to Uint8Array
|
||||||
const header = new TextEncoder().encode('sim-v1');
|
const header = new TextEncoder().encode('sim-v1');
|
||||||
@@ -73,7 +101,7 @@ export async function runSimulation(
|
|||||||
throw new Error('Invalid block hash format');
|
throw new Error('Invalid block hash format');
|
||||||
}
|
}
|
||||||
const hashBytes = new Uint8Array(
|
const hashBytes = new Uint8Array(
|
||||||
matches.map((byte) => Number.parseInt(byte, 16))
|
matches.map((byte) => Number.parseInt(byte, 16)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Convert transactions to bytes
|
// Convert transactions to bytes
|
||||||
@@ -128,10 +156,12 @@ export class SimulationBuilder {
|
|||||||
private constructor(options: SimulationBuilderOptions = {}) {
|
private constructor(options: SimulationBuilderOptions = {}) {
|
||||||
this.network = options.network ?? 'mainnet';
|
this.network = options.network ?? 'mainnet';
|
||||||
const isTestnet = this.network === 'testnet';
|
const isTestnet = this.network === 'testnet';
|
||||||
|
|
||||||
this.apiEndpoint = options.apiEndpoint ??
|
this.apiEndpoint =
|
||||||
|
options.apiEndpoint ??
|
||||||
(isTestnet ? 'https://testnet-api.stxer.xyz' : 'https://api.stxer.xyz');
|
(isTestnet ? 'https://testnet-api.stxer.xyz' : 'https://api.stxer.xyz');
|
||||||
this.stacksNodeAPI = options.stacksNodeAPI ??
|
this.stacksNodeAPI =
|
||||||
|
options.stacksNodeAPI ??
|
||||||
(isTestnet ? 'https://api.testnet.hiro.so' : 'https://api.hiro.so');
|
(isTestnet ? 'https://api.testnet.hiro.so' : 'https://api.hiro.so');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,37 +169,37 @@ export class SimulationBuilder {
|
|||||||
return new SimulationBuilder(options);
|
return new SimulationBuilder(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// biome-ignore lint/style/useNumberNamespace: <explanation>
|
// biome-ignore lint/style/useNumberNamespace: ignore this
|
||||||
private block = NaN;
|
private block = NaN;
|
||||||
private sender = '';
|
private sender = '';
|
||||||
private steps: (
|
private steps: (
|
||||||
| {
|
| {
|
||||||
// inline simulation
|
// inline simulation
|
||||||
simulationId: string;
|
simulationId: string;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
// contract call
|
// contract call
|
||||||
contract_id: string;
|
contract_id: string;
|
||||||
function_name: string;
|
function_name: string;
|
||||||
function_args?: ClarityValue[];
|
function_args?: ClarityValue[];
|
||||||
sender: string;
|
sender: string;
|
||||||
fee: number;
|
fee: number;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
// contract deploy
|
// contract deploy
|
||||||
contract_name: string;
|
contract_name: string;
|
||||||
source_code: string;
|
source_code: string;
|
||||||
deployer: string;
|
deployer: string;
|
||||||
fee: number;
|
fee: number;
|
||||||
clarity_version: ClarityVersion;
|
clarity_version: ClarityVersion;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
// STX transfer
|
// STX transfer
|
||||||
recipient: string;
|
recipient: string;
|
||||||
amount: number;
|
amount: number;
|
||||||
sender: string;
|
sender: string;
|
||||||
fee: number;
|
fee: number;
|
||||||
}
|
}
|
||||||
| SimulationEval
|
| SimulationEval
|
||||||
)[] = [];
|
)[] = [];
|
||||||
|
|
||||||
@@ -184,7 +214,7 @@ export class SimulationBuilder {
|
|||||||
public inlineSimulation(simulationId: string) {
|
public inlineSimulation(simulationId: string) {
|
||||||
this.steps.push({
|
this.steps.push({
|
||||||
simulationId,
|
simulationId,
|
||||||
})
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public addSTXTransfer(params: {
|
public addSTXTransfer(params: {
|
||||||
@@ -195,7 +225,7 @@ export class SimulationBuilder {
|
|||||||
}) {
|
}) {
|
||||||
if (params.sender == null && this.sender === '') {
|
if (params.sender == null && this.sender === '') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Please specify a sender with useSender or adding a sender paramenter'
|
'Please specify a sender with useSender or adding a sender paramenter',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.steps.push({
|
this.steps.push({
|
||||||
@@ -214,7 +244,7 @@ export class SimulationBuilder {
|
|||||||
}) {
|
}) {
|
||||||
if (params.sender == null && this.sender === '') {
|
if (params.sender == null && this.sender === '') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Please specify a sender with useSender or adding a sender paramenter'
|
'Please specify a sender with useSender or adding a sender paramenter',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.steps.push({
|
this.steps.push({
|
||||||
@@ -233,7 +263,7 @@ export class SimulationBuilder {
|
|||||||
}) {
|
}) {
|
||||||
if (params.deployer == null && this.sender === '') {
|
if (params.deployer == null && this.sender === '') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Please specify a deployer with useSender or adding a deployer paramenter'
|
'Please specify a deployer with useSender or adding a deployer paramenter',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.steps.push({
|
this.steps.push({
|
||||||
@@ -274,7 +304,7 @@ export class SimulationBuilder {
|
|||||||
this.block = stacks_tip_height;
|
this.block = stacks_tip_height;
|
||||||
}
|
}
|
||||||
const info: Block = await richFetch(
|
const info: Block = await richFetch(
|
||||||
`${this.stacksNodeAPI}/extended/v1/block/by_height/${this.block}?unanchored=true`
|
`${this.stacksNodeAPI}/extended/v1/block/by_height/${this.block}?unanchored=true`,
|
||||||
).then((r) => r.json());
|
).then((r) => r.json());
|
||||||
if (
|
if (
|
||||||
info.height !== this.block ||
|
info.height !== this.block ||
|
||||||
@@ -282,7 +312,7 @@ export class SimulationBuilder {
|
|||||||
!info.hash.startsWith('0x')
|
!info.hash.startsWith('0x')
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`failed to get block info for block height ${this.block}`
|
`failed to get block info for block height ${this.block}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -302,21 +332,22 @@ SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER
|
|||||||
|
|
||||||
Feedbacks and feature requests are welcome.
|
Feedbacks and feature requests are welcome.
|
||||||
To get in touch: contact@stxer.xyz
|
To get in touch: contact@stxer.xyz
|
||||||
--------------------------------`
|
--------------------------------`,
|
||||||
);
|
);
|
||||||
const block = await this.getBlockInfo();
|
const block = await this.getBlockInfo();
|
||||||
console.log(
|
console.log(
|
||||||
`Using block height ${block.block_height} hash 0x${block.block_hash} to run simulation.`
|
`Using block height ${block.block_height} hash 0x${block.block_hash} to run simulation.`,
|
||||||
);
|
);
|
||||||
const txs: (StacksTransactionWire | SimulationEval)[] = [];
|
const txs: (StacksTransactionWire | SimulationEval)[] = [];
|
||||||
const nonce_by_address = new Map<string, number>();
|
const nonce_by_address = new Map<string, number>();
|
||||||
const nextNonce = async (sender: string) => {
|
const nextNonce = async (sender: string) => {
|
||||||
const nonce = nonce_by_address.get(sender);
|
const nonce = nonce_by_address.get(sender);
|
||||||
if (nonce == null) {
|
if (nonce == null) {
|
||||||
const url = `${this.stacksNodeAPI
|
const url = `${
|
||||||
}/v2/accounts/${sender}?proof=${false}&tip=${block.index_block_hash}`;
|
this.stacksNodeAPI
|
||||||
|
}/v2/accounts/${sender}?proof=${false}&tip=${block.index_block_hash}`;
|
||||||
const account: AccountDataResponse = await richFetch(url).then((r) =>
|
const account: AccountDataResponse = await richFetch(url).then((r) =>
|
||||||
r.json()
|
r.json(),
|
||||||
);
|
);
|
||||||
nonce_by_address.set(sender, account.nonce + 1);
|
nonce_by_address.set(sender, account.nonce + 1);
|
||||||
return account.nonce;
|
return account.nonce;
|
||||||
@@ -336,7 +367,21 @@ To get in touch: contact@stxer.xyz
|
|||||||
}
|
}
|
||||||
for (const step of this.steps) {
|
for (const step of this.steps) {
|
||||||
if ('simulationId' in step) {
|
if ('simulationId' in step) {
|
||||||
const previousSimulation: {steps: ({tx: string} | {code: string, contract: string})[]} = await fetch(`https://api.stxer.xyz/simulations/${step.simulationId}/request`).then(x => x.json())
|
const previousSimulation: {
|
||||||
|
steps: ({ tx: string } | { code: string; contract: string })[];
|
||||||
|
} = await fetch(
|
||||||
|
`https://api.stxer.xyz/simulations/${step.simulationId}/request`,
|
||||||
|
).then(async (rs) => {
|
||||||
|
const body = await rs.text();
|
||||||
|
if (!body.startsWith('{')) {
|
||||||
|
throw new Error(
|
||||||
|
`failed to get simulation ${step.simulationId}: ${body}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return JSON.parse(body) as {
|
||||||
|
steps: ({ tx: string } | { code: string; contract: string })[];
|
||||||
|
};
|
||||||
|
});
|
||||||
for (const step of previousSimulation.steps) {
|
for (const step of previousSimulation.steps) {
|
||||||
if ('tx' in step) {
|
if ('tx' in step) {
|
||||||
txs.push(deserializeTransaction(step.tx));
|
txs.push(deserializeTransaction(step.tx));
|
||||||
@@ -361,7 +406,7 @@ To get in touch: contact@stxer.xyz
|
|||||||
postConditionMode: PostConditionMode.Allow,
|
postConditionMode: PostConditionMode.Allow,
|
||||||
fee: step.fee,
|
fee: step.fee,
|
||||||
});
|
});
|
||||||
tx.auth.spendingCondition.signer = c32addressDecode(step.sender)[1];
|
setSender(tx, step.sender);
|
||||||
txs.push(tx);
|
txs.push(tx);
|
||||||
} else if ('sender' in step && 'recipient' in step) {
|
} else if ('sender' in step && 'recipient' in step) {
|
||||||
const nonce = await nextNonce(step.sender);
|
const nonce = await nextNonce(step.sender);
|
||||||
@@ -373,7 +418,7 @@ To get in touch: contact@stxer.xyz
|
|||||||
publicKey: '',
|
publicKey: '',
|
||||||
fee: step.fee,
|
fee: step.fee,
|
||||||
});
|
});
|
||||||
tx.auth.spendingCondition.signer = c32addressDecode(step.sender)[1];
|
setSender(tx, step.sender);
|
||||||
txs.push(tx);
|
txs.push(tx);
|
||||||
} else if ('deployer' in step) {
|
} else if ('deployer' in step) {
|
||||||
const nonce = await nextNonce(step.deployer);
|
const nonce = await nextNonce(step.deployer);
|
||||||
@@ -386,28 +431,29 @@ To get in touch: contact@stxer.xyz
|
|||||||
postConditionMode: PostConditionMode.Allow,
|
postConditionMode: PostConditionMode.Allow,
|
||||||
fee: step.fee,
|
fee: step.fee,
|
||||||
});
|
});
|
||||||
tx.auth.spendingCondition.signer = c32addressDecode(step.deployer)[1];
|
setSender(tx, step.deployer);
|
||||||
txs.push(tx);
|
txs.push(tx);
|
||||||
} else if ('code' in step) {
|
} else if ('code' in step) {
|
||||||
txs.push(step);
|
txs.push(step);
|
||||||
} else {
|
} else {
|
||||||
// biome-ignore lint/style/noUnusedTemplateLiteral: <explanation>
|
console.log(`Invalid simulation step: ${step}`);
|
||||||
console.log(`Invalid simulation step:`, step);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const id = await runSimulation(
|
const id = await runSimulation(
|
||||||
`${this.apiEndpoint}/simulations`,
|
`${this.apiEndpoint}/simulations`,
|
||||||
block.block_hash,
|
block.block_hash,
|
||||||
block.block_height,
|
block.block_height,
|
||||||
txs
|
txs,
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`Simulation will be available at: https://stxer.xyz/simulations/${this.network}/${id}`
|
`Simulation will be available at: https://stxer.xyz/simulations/${this.network}/${id}`,
|
||||||
);
|
);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public pipe(transform: (builder: SimulationBuilder) => SimulationBuilder): SimulationBuilder {
|
public pipe(
|
||||||
|
transform: (builder: SimulationBuilder) => SimulationBuilder,
|
||||||
|
): SimulationBuilder {
|
||||||
return transform(this);
|
return transform(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user