@stellar/stellar-sdk
Version:
A library for working with the Stellar network, including communication with the Horizon and Soroban RPC servers.
226 lines (223 loc) • 8.98 kB
JavaScript
import { Buffer } from 'buffer';
import '../node_modules/.pnpm/@stellar_js-xdr@4.0.0/node_modules/@stellar/js-xdr/src/int.js';
import '../node_modules/.pnpm/@stellar_js-xdr@4.0.0/node_modules/@stellar/js-xdr/src/hyper.js';
import '../node_modules/.pnpm/@stellar_js-xdr@4.0.0/node_modules/@stellar/js-xdr/src/unsigned-int.js';
import '../node_modules/.pnpm/@stellar_js-xdr@4.0.0/node_modules/@stellar/js-xdr/src/unsigned-hyper.js';
import '../node_modules/.pnpm/@stellar_js-xdr@4.0.0/node_modules/@stellar/js-xdr/src/xdr-type.js';
import types from '../base/generated/curr_generated.js';
import '@noble/hashes/sha2.js';
import '../base/signing.js';
import '../base/keypair.js';
import 'base32.js';
import { Operation } from '../base/operation.js';
import '../base/util/bignumber.js';
import '../base/transaction_builder.js';
import '../base/muxed_account.js';
import { Address } from '../base/address.js';
import '../base/scval.js';
import '../base/numbers/uint128.js';
import '../base/numbers/uint256.js';
import '../base/numbers/int128.js';
import '../base/numbers/int256.js';
import { Spec } from './spec.js';
import '../rpc/api.js';
import { RpcServer } from '../rpc/server.js';
import { AssembledTransaction } from './assembled_transaction.js';
import { sanitizeIdentifier } from '../bindings/utils.js';
const CONSTRUCTOR_FUNC = "__constructor";
async function specFromWasmHash(wasmHash, options, format = "hex") {
if (!options || !options.rpcUrl) {
throw new TypeError("options must contain rpcUrl");
}
const { rpcUrl, allowHttp, headers } = options;
const serverOpts = { allowHttp, headers };
const server = new RpcServer(rpcUrl, serverOpts);
const wasm = await server.getContractWasmByHash(wasmHash, format);
return Spec.fromWasm(wasm);
}
class Client {
constructor(spec, options) {
this.spec = spec;
this.options = options;
if (options.server === void 0) {
const { allowHttp, headers } = options;
options.server = new RpcServer(options.rpcUrl, {
allowHttp,
headers
});
}
this.spec.funcs().forEach((xdrFn) => {
const method = xdrFn.name().toString();
if (method === CONSTRUCTOR_FUNC) {
return;
}
const assembleTransaction = (args, methodOptions) => AssembledTransaction.build({
method,
args: args && spec.funcArgsToScVals(method, args),
...options,
...methodOptions,
errorTypes: spec.errorCases().reduce(
(acc, curr) => ({
...acc,
[curr.value()]: { message: curr.doc().toString() }
}),
{}
),
parseResultXdr: (result) => spec.funcResToNative(method, result)
});
this[sanitizeIdentifier(method)] = spec.getFunc(method).inputs().length === 0 ? (opts) => assembleTransaction(void 0, opts) : assembleTransaction;
});
}
spec;
options;
static async deploy(args, options) {
const {
wasmHash,
salt,
format,
fee,
timeoutInSeconds,
simulate,
...clientOptions
} = options;
const spec = await specFromWasmHash(wasmHash, clientOptions, format);
const operation = Operation.createCustomContract({
address: new Address(options.address || options.publicKey),
wasmHash: typeof wasmHash === "string" ? Buffer.from(wasmHash, format ?? "hex") : wasmHash,
salt,
constructorArgs: args ? spec.funcArgsToScVals(CONSTRUCTOR_FUNC, args) : []
});
return AssembledTransaction.buildWithOp(operation, {
fee,
timeoutInSeconds,
simulate,
...clientOptions,
contractId: "ignored",
method: CONSTRUCTOR_FUNC,
parseResultXdr: (result) => new Client(spec, {
...clientOptions,
contractId: Address.fromScVal(result).toString()
})
});
}
/**
* Generates a Client instance from the provided ClientOptions and the contract's wasm hash.
* The wasmHash can be provided in either hex or base64 format.
*
* @typeParam T - An interface describing the contract's methods, used to type
* the returned client. Defaults to `unknown`, so calling without a type
* argument yields a plain `Client` (backward compatible). Provide it to get
* typed, autocompleted contract methods without code generation.
*
* @param wasmHash - The hash of the contract's wasm binary, in either hex or base64 format.
* @param options - The ClientOptions object containing the necessary configuration, including the rpcUrl.
* @param format - (optional) The format of the provided wasmHash, either "hex" or "base64". Defaults to "hex".
* @returns A Promise that resolves to a Client instance.
* @throws If the provided options object does not contain an rpcUrl.
*
* @example
* ```ts
* interface MyContract {
* increment: (opts?: MethodOptions) => Promise<AssembledTransaction<number>>;
* }
* const client = await contract.Client.fromWasmHash<MyContract>(hash, options);
* const tx = await client.increment(); // typed
* ```
*/
static async fromWasmHash(wasmHash, options, format = "hex") {
if (!options || !options.rpcUrl) {
throw new TypeError("options must contain rpcUrl");
}
const { rpcUrl, allowHttp, headers } = options;
const server = options.server ?? new RpcServer(rpcUrl, {
allowHttp,
headers
});
const wasm = await server.getContractWasmByHash(wasmHash, format);
return Client.fromWasm(wasm, options);
}
/**
* Generates a Client instance from the provided ClientOptions and the contract's wasm binary.
*
* @typeParam T - An interface describing the contract's methods, used to type
* the returned client. Defaults to `unknown`, so calling without a type
* argument yields a plain `Client` (backward compatible). Provide it to get
* typed, autocompleted contract methods without code generation.
*
* @param wasm - The contract's wasm binary as a Buffer.
* @param options - The ClientOptions object containing the necessary configuration.
* @returns A Promise that resolves to a Client instance.
* @throws If the contract spec cannot be obtained from the provided wasm binary.
*
* @example
* ```ts
* interface MyContract {
* increment: (opts?: MethodOptions) => Promise<AssembledTransaction<number>>;
* }
* const client = await contract.Client.fromWasm<MyContract>(wasm, options);
* const tx = await client.increment(); // typed
* ```
*/
static async fromWasm(wasm, options) {
const spec = await Spec.fromWasm(wasm);
return new Client(spec, options);
}
/**
* Generates a Client instance from the provided ClientOptions, which must include the contractId and rpcUrl.
*
* If the contract is a built-in Stellar Asset Contract (SAC), the embedded
* SAC spec is used instead of downloading Wasm, since a SAC has no Wasm
* executable on-chain.
*
* @typeParam T - An interface describing the contract's methods, used to type
* the returned client. Defaults to `unknown`, so calling without a type
* argument yields a plain `Client` (backward compatible). Provide it to get
* typed, autocompleted contract methods without code generation.
*
* @param options - The ClientOptions object containing the necessary configuration, including the contractId and rpcUrl.
* @returns A Promise that resolves to a Client instance.
* @throws If the provided options object does not contain both rpcUrl and contractId.
*
* @example
* ```ts
* interface MyContract {
* increment: (opts?: MethodOptions) => Promise<AssembledTransaction<number>>;
* }
* const client = await contract.Client.from<MyContract>(options);
* const tx = await client.increment(); // typed
* ```
*/
static async from(options) {
if (!options || !options.rpcUrl || !options.contractId) {
throw new TypeError("options must contain rpcUrl and contractId");
}
const { rpcUrl, contractId, allowHttp, headers } = options;
const server = options.server ?? new RpcServer(rpcUrl, {
allowHttp,
headers
});
const instance = await server.getContractInstance(contractId);
if (instance.executable().switch() === types.ContractExecutableType.contractExecutableStellarAsset()) {
const { SAC_SPEC } = await import('../bindings/sac-spec.js');
return new Client(new Spec(SAC_SPEC), options);
}
const wasm = await server.getContractWasmByHash(
instance.executable().wasmHash()
);
return Client.fromWasm(wasm, options);
}
txFromJSON = (json) => {
const { method, ...tx } = JSON.parse(json);
return AssembledTransaction.fromJSON(
{
...this.options,
method,
parseResultXdr: (result) => this.spec.funcResToNative(method, result)
},
tx
);
};
txFromXDR = (xdrBase64) => AssembledTransaction.fromXDR(this.options, xdrBase64, this.spec);
}
export { Client };
//# sourceMappingURL=client.js.map