diff --git a/src/governor.ts b/src/governor.ts index 86f7526..857c5f1 100644 --- a/src/governor.ts +++ b/src/governor.ts @@ -9,6 +9,7 @@ import { buildContractCallTx, simulateReadOnly, scValToI128, + scValToU32, scValToU64, NETWORK_PASSPHRASE, DEFAULT_RPC, @@ -65,8 +66,9 @@ function parseGovernorConfig(val: xdr.ScVal): GovernorConfig { m[k] = e.val(); } return { - feeBps: m['fee_bps']?.u32() ?? 0, + feeBps: m['fee_bps'] ? scValToU32(m['fee_bps']) : 0, minDurationSeconds: m['min_duration_seconds'] ? Number(scValToU64(m['min_duration_seconds'])) : 0, + maxDurationSeconds: m['max_duration_seconds'] ? Number(scValToU64(m['max_duration_seconds'])) : 0, maxRatePerSecond: m['max_rate_per_second'] ? scValToI128(m['max_rate_per_second']) : 0n, // exactOptionalPropertyTypes forbids assigning `undefined` to an optional // key directly — the key must be entirely absent instead, hence the diff --git a/src/indexer.ts b/src/indexer.ts index 16968b3..1a451ab 100644 --- a/src/indexer.ts +++ b/src/indexer.ts @@ -1,5 +1,6 @@ import { ConduitError, UNKNOWN_CONTRACT_ERROR_CODE } from './errors.js'; import { IndexerTimeoutError, OperationAbortedError } from './errors.js'; +import { bigintSafeStringify } from './utils.js'; export interface GraphQLQueryOptions { query: string; @@ -206,7 +207,7 @@ export class GraphQLIndexer { fetchFn, this.endpoint, headers, - JSON.stringify(payload), + JSON.stringify({ ...payload, variables: bigintSafeStringify(payload.variables) }), timeoutMs, callerSignal, ); @@ -407,7 +408,7 @@ export class GraphQLIndexer { type: 'subscribe', payload: { query: options.query, - variables, + variables: bigintSafeStringify(variables), }, }); } catch (err) { @@ -493,7 +494,7 @@ export class GraphQLIndexer { fetchFn(this.endpoint, { method: 'POST', headers, - body: JSON.stringify({ query: options.query, variables }), + body: JSON.stringify({ query: options.query, variables: bigintSafeStringify(variables) }), signal: abortController.signal, }) .then(async (response: Response) => { diff --git a/src/soroban.ts b/src/soroban.ts index b85607b..63d98a6 100644 --- a/src/soroban.ts +++ b/src/soroban.ts @@ -305,7 +305,7 @@ export async function getTokenDecimals( const promise = (async () => { const tx = await buildContractCallTx(rpcUrl, passphrase, callerAddr, tokenId, 'decimals', []); const val = await simulateReadOnly(rpcUrl, passphrase, tx); - return val.u32(); + return scValToU32(val); })(); _tokenDecimalsCache.set(cacheKey, promise); diff --git a/src/types/index.ts b/src/types/index.ts index 7ab37ec..3be6bef 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -144,6 +144,7 @@ export interface GovernorConfig { feeBps: number; feeRecipient?: string; minDurationSeconds: number; + maxDurationSeconds: number; maxRatePerSecond: bigint; factoryAddress?: string; } diff --git a/src/utils.ts b/src/utils.ts index 162e8c2..18254b2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -37,16 +37,18 @@ export function toStroops(amount: string, decimals = 7): bigint { /** Convert stroops (bigint) to a display amount string */ export function fromStroops(stroops: bigint, decimals = 7): string { + const neg = stroops < 0n; + const abs = neg ? -stroops : stroops; const factor = pow10(decimals); - const whole = stroops / factor; - const rem = stroops % factor; + const whole = abs / factor; + const rem = abs % factor; const frac = rem.toString().padStart(decimals, '0'); let end = frac.length; while (end > 1 && frac.charCodeAt(end - 1) === 48) { end--; } const trimmed = frac.slice(0, end); - return `${whole}.${trimmed}`; + return `${neg ? '-' : ''}${whole}.${trimmed}`; } /**