mirror of
https://github.com/stxer/stxer-sdk.git
synced 2026-01-12 22:31:05 +08:00
feat: update batch api
This commit is contained in:
157
src/batch-api.ts
157
src/batch-api.ts
@@ -1,12 +1,19 @@
|
||||
/**
|
||||
* WARNING:
|
||||
*
|
||||
* this file will be used in cross-runtime environments (browser, cloudflare workers, XLinkSDK, etc.),
|
||||
* so please be careful when adding `import`s to it.
|
||||
*/
|
||||
|
||||
import {
|
||||
type ClarityValue,
|
||||
type ContractPrincipalCV,
|
||||
deserializeCV,
|
||||
type OptionalCV,
|
||||
serializeCV,
|
||||
} from '@stacks/transactions';
|
||||
} from '@stacks/transactions';
|
||||
|
||||
export interface BatchReads {
|
||||
export interface BatchReads {
|
||||
variables?: {
|
||||
contract: ContractPrincipalCV;
|
||||
variableName: string;
|
||||
@@ -16,33 +23,68 @@ import {
|
||||
mapName: string;
|
||||
mapKey: ClarityValue;
|
||||
}[];
|
||||
readonly?: {
|
||||
contract: ContractPrincipalCV;
|
||||
functionName: string;
|
||||
functionArgs: ClarityValue[];
|
||||
}[];
|
||||
index_block_hash?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface BatchReadsResult {
|
||||
variables: (ClarityValue | Error)[];
|
||||
maps: (OptionalCV | Error)[];
|
||||
}
|
||||
export interface BatchReadsResult {
|
||||
tip: string;
|
||||
vars: (ClarityValue | Error)[];
|
||||
maps: (ClarityValue | Error)[];
|
||||
readonly: (ClarityValue | Error)[];
|
||||
}
|
||||
|
||||
export interface BatchApiOptions {
|
||||
export interface BatchApiOptions {
|
||||
stxerApi?: string;
|
||||
}
|
||||
|
||||
const DEFAULT_STXER_API = 'https://api.stxer.xyz';
|
||||
|
||||
function convertResults(
|
||||
rs: ({ Ok: string } | { Err: string })[],
|
||||
): (ClarityValue | Error)[] {
|
||||
const results: (ClarityValue | Error)[] = [];
|
||||
for (const v of rs) {
|
||||
if ('Ok' in v) {
|
||||
results.push(deserializeCV(v.Ok));
|
||||
} else {
|
||||
results.push(new Error(v.Err));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
const DEFAULT_STXER_API = 'https://api.stxer.xyz';
|
||||
|
||||
export async function batchRead(
|
||||
export async function batchRead(
|
||||
reads: BatchReads,
|
||||
options: BatchApiOptions = {}
|
||||
): Promise<BatchReadsResult> {
|
||||
const payload: string[][] = [];
|
||||
): Promise<BatchReadsResult> {
|
||||
const ibh =
|
||||
reads.index_block_hash == null
|
||||
? undefined
|
||||
: reads.index_block_hash.startsWith('0x')
|
||||
? reads.index_block_hash.substring(2)
|
||||
: reads.index_block_hash;
|
||||
|
||||
const payload: {
|
||||
tip?: string;
|
||||
vars: string[][];
|
||||
maps: string[][];
|
||||
readonly: string[][];
|
||||
} = { vars: [], maps: [], readonly: [], tip: ibh };
|
||||
|
||||
if (reads.variables != null) {
|
||||
for (const variable of reads.variables) {
|
||||
payload.push([serializeCV(variable.contract), variable.variableName]);
|
||||
payload.vars.push([serializeCV(variable.contract), variable.variableName]);
|
||||
}
|
||||
}
|
||||
|
||||
if (reads.maps != null) {
|
||||
for (const map of reads.maps) {
|
||||
payload.push([
|
||||
payload.maps.push([
|
||||
serializeCV(map.contract),
|
||||
map.mapName,
|
||||
serializeCV(map.mapKey),
|
||||
@@ -50,71 +92,62 @@ import {
|
||||
}
|
||||
}
|
||||
|
||||
const ibh =
|
||||
reads.index_block_hash == null
|
||||
? null
|
||||
: reads.index_block_hash.startsWith('0x')
|
||||
? reads.index_block_hash.substring(2)
|
||||
: reads.index_block_hash;
|
||||
if (reads.readonly != null) {
|
||||
for (const ro of reads.readonly) {
|
||||
payload.readonly.push([
|
||||
serializeCV(ro.contract),
|
||||
ro.functionName,
|
||||
...ro.functionArgs.map(v => serializeCV(v)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const url = `${options.stxerApi ?? DEFAULT_STXER_API}/sidecar/v2/batch-reads${
|
||||
ibh == null ? '' : `?tip=${ibh}`
|
||||
}`;
|
||||
const url = `${options.stxerApi ?? DEFAULT_STXER_API}/sidecar/v2/batch`;
|
||||
const data = await fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
const text = await data.text();
|
||||
if (!text.includes('Ok') && !text.includes('Err')) {
|
||||
throw new Error(
|
||||
`Requesting batch reads failed: ${text}, url: ${url}, payload: ${JSON.stringify(
|
||||
payload
|
||||
)}`
|
||||
payload,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
const results = JSON.parse(text) as [{ Ok: string } | { Err: string }];
|
||||
const rs: BatchReadsResult = {
|
||||
variables: [],
|
||||
maps: [],
|
||||
};
|
||||
let variablesLength = 0;
|
||||
if (reads.variables != null) {
|
||||
variablesLength = reads.variables.length;
|
||||
for (let i = 0; i < variablesLength; i++) {
|
||||
const result = results[i];
|
||||
if ('Ok' in result) {
|
||||
rs.variables.push(deserializeCV(result.Ok));
|
||||
} else {
|
||||
rs.variables.push(new Error(result.Err));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reads.maps != null) {
|
||||
for (let i = 0; i < reads.maps.length; i++) {
|
||||
const result = results[i + variablesLength];
|
||||
if ('Ok' in result) {
|
||||
rs.maps.push(deserializeCV(result.Ok) as OptionalCV);
|
||||
} else {
|
||||
rs.maps.push(new Error(result.Err));
|
||||
}
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
export interface BatchReadonlyRequest {
|
||||
const rs = JSON.parse(text) as {
|
||||
tip: string;
|
||||
vars: ({ Ok: string } | { Err: string })[];
|
||||
maps: ({ Ok: string } | { Err: string })[];
|
||||
readonly: ({ Ok: string } | { Err: string })[];
|
||||
};
|
||||
|
||||
return {
|
||||
tip: rs.tip,
|
||||
vars: convertResults(rs.vars),
|
||||
maps: convertResults(rs.maps),
|
||||
readonly: convertResults(rs.readonly),
|
||||
};
|
||||
}
|
||||
|
||||
export interface BatchReadonlyRequest {
|
||||
readonly: {
|
||||
contract: ContractPrincipalCV;
|
||||
functionName: string;
|
||||
functionArgs: ClarityValue[];
|
||||
}[];
|
||||
index_block_hash?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export async function batchReadonly(
|
||||
export async function batchReadonly(
|
||||
req: BatchReadonlyRequest,
|
||||
options: BatchApiOptions = {}
|
||||
): Promise<(ClarityValue | Error)[]> {
|
||||
): Promise<(ClarityValue | Error)[]> {
|
||||
const payload = req.readonly.map((r) => [
|
||||
serializeCV(r.contract),
|
||||
r.functionName,
|
||||
@@ -128,8 +161,7 @@ import {
|
||||
? req.index_block_hash.substring(2)
|
||||
: req.index_block_hash;
|
||||
|
||||
const url = `${options.stxerApi ?? DEFAULT_STXER_API}/sidecar/v2/batch-readonly${
|
||||
ibh == null ? '' : `?tip=${ibh}`
|
||||
const url = `${options.stxerApi ?? DEFAULT_STXER_API}/sidecar/v2/batch-readonly${ibh == null ? '' : `?tip=${ibh}`
|
||||
}`;
|
||||
const data = await fetch(url, {
|
||||
method: 'POST',
|
||||
@@ -153,5 +185,4 @@ import {
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ import {
|
||||
|
||||
async function main() {
|
||||
await batchReadsExample();
|
||||
await batchReadonlyExample();
|
||||
// await batchReadonlyExample();
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
Reference in New Issue
Block a user