Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
/jsdoc/
.DS_Store
.vscode/settings.json
.copilot/
.claude/
.idea/
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
"test": "pnpm run build && pnpm run test:node && pnpm run test:browser",
"test:node": "NODE_OPTIONS=--no-experimental-detect-module pnpm run _nyc -- mocha --config ./mocharc.tsnode.json",
"test:browser": "karma start ./config/karma.conf.js",
"test:vitest": "vitest",
"test:vitest": "vitest --run",
"test:vitest:ui": "vitest --ui",
"test:vitest:watch": "vitest",
"test:vitest:coverage": "vitest --coverage",
"docs": "jsdoc -c ./config/.jsdoc.json --verbose",
"lint": "eslint -c ./config/eslint.config.cjs src/ && dtslint --localTs node_modules/typescript/lib types/",
Expand Down
121 changes: 121 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* eslint-disable import-x/extensions */
/**
* Temporary type declaration file for src/index.js
* This will be removed once src/index.js is migrated to TypeScript
*/

import xdr from "./xdr";

// Re-export xdr and cereal
export { xdr };
export { cereal } from "./jsxdr";

// From ./numbers
export { ScInt } from "./numbers/index";
export { XdrLargeInt } from "./numbers/index";
export { scValToBigInt } from "./numbers/index";

// From ./scval
export function nativeToScVal(
val: unknown,
opts?: { type?: Record<string, unknown> | string[] | string },
): xdr.ScVal;

export function scValToNative(scv: xdr.ScVal): unknown;

// From ./address
export class Address {
constructor(address: string);
toScVal(): xdr.ScVal;
toString(): string;
}

// From ./keypair
export class Keypair {
static random(): Keypair;
publicKey(): string;
}

// All other exports
export function hash(data: Buffer): Buffer;
export function sign(data: Buffer, keypair: Keypair): Buffer;
export function verify(
data: Buffer,
signature: Buffer,
publicKey: string,
): boolean;

export function getLiquidityPoolId(
liquidityPoolType: string,
assets: unknown[],
): string;
export const LiquidityPoolFeeV18: number;

export { UnsignedHyper, Hyper } from "@stellar/js-xdr";

export class TransactionBase {}
export class Transaction extends TransactionBase {}
export class FeeBumpTransaction {}

export class TransactionBuilder {
constructor(sourceAccount: unknown, opts: unknown);
}
export const TimeoutInfinite: number;
export const BASE_FEE: string;

export class Asset {}
export class LiquidityPoolAsset {}
export class LiquidityPoolId {}

export class Operation {}
export const AuthRequiredFlag: number;
export const AuthRevocableFlag: number;
export const AuthImmutableFlag: number;
export const AuthClawbackEnabledFlag: number;

export class MemoNone {}
export class MemoText {
constructor(text: string);
}
export class MemoId {
constructor(id: string);
}
export class MemoHash {
constructor(hash: Buffer);
}
export class MemoReturnHash {
constructor(hash: Buffer);
}

export class Account {}
export class MuxedAccount {}
export class Claimant {}

export const Networks: { PUBLIC_NETWORK_PASSPHRASE: string };

export class StrKey {}
export class SignerKey {}
export class Soroban {}

export function decodeAddressToMuxedAccount(address: string): unknown;
export function encodeMuxedAccountToAddress(
accountId: string,
muxId?: string,
): string;
export function extractBaseAddress(address: string): string;
export function encodeMuxedAccount(accountId: string, muxId?: string): string;

export class Contract {}

// Re-export everything from numbers
export * from "./numbers/index.js";

// Re-export everything from scval (nativeToScVal and scValToNative already declared)
export * from "./scval.js";

export * from "./events.js";
export * from "./sorobandata_builder.js";
export * from "./auth.js";
export * from "./invocation.js";

export default module.exports;
61 changes: 0 additions & 61 deletions src/numbers/index.js

This file was deleted.

73 changes: 73 additions & 0 deletions src/numbers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import xdr from "../xdr.js";
import { XdrLargeInt, type ScIntType } from "./xdr_large_int.js";

export { Uint128 } from "./uint128.js";
export { Uint256 } from "./uint256.js";
export { Int128 } from "./int128.js";
export { Int256 } from "./int256.js";
export { ScInt } from "./sc_int.js";
export { XdrLargeInt };
export type { ScIntType };

/**
* Transforms an opaque {@link xdr.ScVal} into a native bigint, if possible.
*
* If you then want to use this in the abstractions provided by this module,
* you can pass it to the constructor of {@link XdrLargeInt}.
*
* @example
* let scv = contract.call("add", x, y); // assume it returns an xdr.ScVal
* let bigi = scValToBigInt(scv);
*
* new ScInt(bigi); // if you don't care about types, and
* new XdrLargeInt('i128', bigi); // if you do
*
* @throws {TypeError} if the `scv` input value doesn't represent an integer
*/
export function scValToBigInt(scv: xdr.ScVal): bigint {
const switchName = scv.switch().name;
const scIntType = XdrLargeInt.getType(switchName);
const value = scv.value();

if (value === null) {
throw TypeError(`unexpected null value for ${switchName}`);
}

switch (switchName) {
case "scvU32":
case "scvI32":
return BigInt(value as number);

case "scvU64":
case "scvI64":
case "scvTimepoint":
case "scvDuration":
return new XdrLargeInt(
scIntType as ScIntType,
value as xdr.Int64 | xdr.Uint64,
).toBigInt();

case "scvU128":
case "scvI128": {
const int128Value = value as xdr.Int128Parts | xdr.UInt128Parts;
return new XdrLargeInt(scIntType as ScIntType, [
int128Value.lo(),
int128Value.hi(),
]).toBigInt();
}

case "scvU256":
case "scvI256": {
const int256Value = value as xdr.Int256Parts | xdr.UInt256Parts;
return new XdrLargeInt(scIntType as ScIntType, [
int256Value.loLo(),
int256Value.loHi(),
int256Value.hiLo(),
int256Value.hiHi(),
]).toBigInt();
}

default:
throw TypeError(`expected integer type, got ${switchName}`);
}
}
46 changes: 25 additions & 21 deletions src/numbers/sc_int.js → src/numbers/sc_int.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { XdrLargeInt } from "./xdr_large_int";
import { XdrLargeInt, type ScIntType } from "./xdr_large_int.js";

/**
* Provides an easier way to manipulate large numbers for Stellar operations.
Expand All @@ -24,7 +24,7 @@ import { XdrLargeInt } from "./xdr_large_int";
* sci.toU64(); // gives ScValType-specific XDR constructs (with size checks)
*
* // You have a number and want to shove it into a contract.
* sci = ScInt(0xdeadcafebabe);
* sci = new ScInt(0xdeadcafebabe);
* sci.toBigInt() // returns 244838016400062n
* sci.toNumber() // throws: too large
*
Expand All @@ -35,16 +35,16 @@ import { XdrLargeInt } from "./xdr_large_int";
* const scValU64 = sci.toU64();
*
* // Lots of ways to initialize:
* ScInt("123456789123456789")
* ScInt(123456789123456789n);
* ScInt(1n << 140n);
* ScInt(-42);
* ScInt(scValToBigInt(scValU128)); // from above
* new ScInt("123456789123456789")
* new ScInt(123456789123456789n);
* new ScInt(1n << 140n);
* new ScInt(-42);
* new ScInt(scValToBigInt(scValU128)); // from above
*
* // If you know the type ahead of time (accessing `.raw` is faster than
* // conversions), you can specify the type directly (otherwise, it's
* // interpreted from the numbers you pass in):
* const i = ScInt(123456789n, { type: "u256" });
* const i = new ScInt(123456789n, { type: "u256" });
*
* // For example, you can use the underlying `sdk.U256` and convert it to an
* // `xdr.ScVal` directly like so:
Expand All @@ -53,30 +53,34 @@ import { XdrLargeInt } from "./xdr_large_int";
* // Or reinterpret it as a different type (size permitting):
* const scv = i.toI64();
*
* @param {number|bigint|string} value - a single, integer-like value which will
* @param value - a single, integer-like value which will
* be interpreted in the smallest appropriate XDR type supported by Stellar
* (64, 128, or 256 bit integer values). signed values are supported, though
* they are sanity-checked against `opts.type`. if you need 32-bit values,
* you can construct them directly without needing this wrapper, e.g.
* `xdr.ScVal.scvU32(1234)`.
*
* @param {object} [opts] - an optional object controlling optional parameters
* @param {string} [opts.type] - force a specific data type. the type choices
* are: 'i64', 'u64', 'i128', 'u128', 'i256', and 'u256' (default: the
* smallest one that fits the `value`)
* @param [opts] - an optional object controlling optional parameters
* @param [opts.type] - specify a type ('i64', 'u64', 'i128', 'u128', 'i256',
* or 'u256') to override the default type selection. If not specified, the
* smallest type that fits the value is used.
*
* @throws {RangeError} if the `value` is invalid (e.g. floating point), too
* large (i.e. exceeds a 256-bit value), or doesn't fit in the `opts.type`
* @throws {TypeError} on missing parameters, or if the "signedness" of `opts`
* doesn't match input `value`, e.g. passing `{type: 'u64'}` yet passing -1n
* @throws {TypeError} if the "signedness" of `opts.type` doesn't match the
* input `value`, e.g. passing `{type: 'u64'}` with a negative value like `-1n`
* @throws {SyntaxError} if a string `value` can't be parsed as a big integer
*/
export class ScInt extends XdrLargeInt {
constructor(value, opts) {
const signed = value < 0;
constructor(
value: bigint | number | string,
opts?: { type?: ScIntType; [key: string]: unknown },
) {
const bigValue = typeof value === "bigint" ? value : BigInt(value);
const signed = bigValue < 0;
let type = opts?.type ?? "";
if (type.startsWith("u") && signed) {
throw TypeError(`specified type ${opts.type} yet negative (${value})`);
throw TypeError(`specified type ${opts?.type} yet negative (${value})`);
}

// If unspecified, we make a best guess at the type based on the bit length
Expand All @@ -94,16 +98,16 @@ export class ScInt extends XdrLargeInt {

default:
throw RangeError(
`expected 64/128/256 bits for input (${value}), got ${bitlen}`
`expected 64/128/256 bits for input (${value}), got ${bitlen}`,
);
}
}

super(type, value);
super(type as ScIntType, value);
}
}

function nearestBigIntSize(bigI) {
function nearestBigIntSize(bigI: bigint | number | string): number {
// Note: Even though BigInt.toString(2) includes the negative sign for
// negative values (???), the following is still accurate, because the
// negative sign would be represented by a sign bit.
Expand Down
Loading