@stellar/typescript-wallet-sdk-soroban 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./Helpers";
2
+ export * from "./Types";
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@stellar/typescript-wallet-sdk-soroban",
3
+ "version": "1.5.0",
4
+ "engines": {
5
+ "node": ">=18"
6
+ },
7
+ "browser": "./lib/bundle_browser.js",
8
+ "main": "./lib/bundle.js",
9
+ "types": "./lib/index.d.ts",
10
+ "license": "Apache-2.0",
11
+ "private": false,
12
+ "devDependencies": {
13
+ "@babel/preset-env": "^7.24.0",
14
+ "@babel/preset-typescript": "^7.23.3",
15
+ "@stellar/prettier-config": "^1.0.1",
16
+ "@stellar/tsconfig": "^1.0.2",
17
+ "@types/jest": "^29.5.12",
18
+ "@typescript-eslint/parser": "^7.1.1",
19
+ "babel-jest": "^29.7.0",
20
+ "husky": "^9.0.11",
21
+ "jest": "^29.7.0",
22
+ "npm-run-all": "^4.1.5",
23
+ "ts-jest": "^29.1.2",
24
+ "ts-loader": "^9.5.1",
25
+ "tslib": "^2.6.2",
26
+ "typescript": "^5.3.3",
27
+ "webpack": "^5.90.3",
28
+ "webpack-cli": "^5.1.4"
29
+ },
30
+ "dependencies": {
31
+ "@stellar/stellar-sdk": "^11.1.0"
32
+ },
33
+ "scripts": {
34
+ "prepare": "husky install",
35
+ "test": "jest --watchAll",
36
+ "test:ci": "jest --ci",
37
+ "build:web": "webpack --config webpack.config.js",
38
+ "build:node": "webpack --env NODE=true --config webpack.config.js",
39
+ "build": "run-p build:web build:node"
40
+ }
41
+ }
@@ -0,0 +1,23 @@
1
+ import { Soroban } from "@stellar/stellar-sdk";
2
+
3
+ /**
4
+ * https://github.com/stellar/js-stellar-base/blob/4b510113738aefb5decb31e2ae72c27da5dd7f5c/src/soroban.js
5
+ *
6
+ * Given a whole number smart contract amount of a token and an amount of
7
+ * decimal places (if the token has any), it returns a "display" value.
8
+ *
9
+ * All arithmetic inside the contract is performed on integers to avoid
10
+ * potential precision and consistency issues of floating-point.
11
+ *
12
+ * @param {string | bigint} amount the token amount you want to display
13
+ * @param {number} decimals specify how many decimal places a token has
14
+ *
15
+ * @returns {string} the display value
16
+ * @throws {TypeError} if the given amount has a decimal point already
17
+ * @example
18
+ * formatTokenAmount("123000", 4) === "12.3";
19
+ */
20
+ export const formatTokenAmount = (
21
+ amount: string | bigint,
22
+ decimals: number,
23
+ ): string => Soroban.formatTokenAmount(amount.toString(), decimals);
@@ -0,0 +1,81 @@
1
+ import { Address, Asset, StrKey, xdr } from "@stellar/stellar-sdk";
2
+
3
+ import { InvocationArgs } from "Types";
4
+
5
+ /**
6
+ * Extract invocation args and params from a Soroban authorized invocation
7
+ * tree up to its immediate sub invocations.
8
+ *
9
+ * @param {xdr.SorobanAuthorizedInvocation} invocationTree - The invocation tree.
10
+ *
11
+ * @returns {InvocationArgs[]} A list of user friendly invocation args and params.
12
+ */
13
+ export const getInvocationDetails = (
14
+ invocationTree: xdr.SorobanAuthorizedInvocation,
15
+ ): InvocationArgs[] => {
16
+ const invocations = [
17
+ getInvocationArgs(invocationTree),
18
+ ...invocationTree.subInvocations().map(getInvocationArgs),
19
+ ];
20
+ return invocations.filter(isInvocationArg);
21
+ };
22
+
23
+ const isInvocationArg = (
24
+ invocation: InvocationArgs | undefined,
25
+ ): invocation is InvocationArgs => !!invocation;
26
+
27
+ export const getInvocationArgs = (
28
+ invocation: xdr.SorobanAuthorizedInvocation,
29
+ ): InvocationArgs | undefined => {
30
+ const fn = invocation.function();
31
+
32
+ switch (fn.switch().value) {
33
+ // sorobanAuthorizedFunctionTypeContractFn
34
+ case 0: {
35
+ const _invocation = fn.contractFn();
36
+ const contractId = StrKey.encodeContract(
37
+ _invocation.contractAddress().contractId(),
38
+ );
39
+ const fnName = _invocation.functionName().toString();
40
+ const args = _invocation.args();
41
+ return { fnName, contractId, args, type: "invoke" };
42
+ }
43
+
44
+ // sorobanAuthorizedFunctionTypeCreateContractHostFn
45
+ case 1: {
46
+ const _invocation = fn.createContractHostFn();
47
+ const [exec, preimage] = [
48
+ _invocation.executable(),
49
+ _invocation.contractIdPreimage(),
50
+ ];
51
+
52
+ switch (exec.switch().value) {
53
+ // contractExecutableWasm
54
+ case 0: {
55
+ const details = preimage.fromAddress();
56
+
57
+ return {
58
+ type: "wasm",
59
+ salt: details.salt().toString("hex"),
60
+ hash: exec.wasmHash().toString("hex"),
61
+ address: Address.fromScAddress(details.address()).toString(),
62
+ };
63
+ }
64
+
65
+ // contractExecutableStellarAsset
66
+ case 1:
67
+ return {
68
+ type: "sac",
69
+ asset: Asset.fromOperation(preimage.fromAsset()).toString(),
70
+ };
71
+
72
+ default:
73
+ throw new Error(`unknown creation type: ${JSON.stringify(exec)}`);
74
+ }
75
+ }
76
+
77
+ default: {
78
+ return undefined;
79
+ }
80
+ }
81
+ };
@@ -0,0 +1,94 @@
1
+ import { Operation, StrKey, scValToNative, xdr } from "@stellar/stellar-sdk";
2
+
3
+ import {
4
+ ArgsForTokenInvocation,
5
+ SorobanTokenInterface,
6
+ TokenInvocationArgs,
7
+ } from "../Types";
8
+
9
+ export const getArgsForTokenInvocation = (
10
+ fnName: string,
11
+ args: xdr.ScVal[],
12
+ ): ArgsForTokenInvocation => {
13
+ let amount: bigint | number;
14
+ let from = "";
15
+ let to = "";
16
+
17
+ switch (fnName) {
18
+ case SorobanTokenInterface.transfer:
19
+ from = StrKey.encodeEd25519PublicKey(
20
+ args[0].address().accountId().ed25519(),
21
+ );
22
+ to = StrKey.encodeEd25519PublicKey(
23
+ args[1].address().accountId().ed25519(),
24
+ );
25
+ amount = scValToNative(args[2]);
26
+ break;
27
+ case SorobanTokenInterface.mint:
28
+ to = StrKey.encodeEd25519PublicKey(
29
+ args[0].address().accountId().ed25519(),
30
+ );
31
+ amount = scValToNative(args[1]);
32
+ break;
33
+ default:
34
+ amount = BigInt(0);
35
+ }
36
+
37
+ return { from, to, amount };
38
+ };
39
+
40
+ /**
41
+ * Get params and args related to the invoked contract. It must use a valid
42
+ * "transfer" or "mint" invocation otherwise it will return 'null'.
43
+ *
44
+ * @param {Operation.InvokeHostFunction} hostFn - The invoke host function.
45
+ *
46
+ * @returns {TokenInvocationArgs | null} Params and args related to the
47
+ * "transfer" or "mint" invocation like function name, contract id, from/to
48
+ * addresses and amount.
49
+ */
50
+ export const getTokenInvocationArgs = (
51
+ hostFn: Operation.InvokeHostFunction,
52
+ ): TokenInvocationArgs | null => {
53
+ if (!hostFn?.func?.invokeContract) {
54
+ return null;
55
+ }
56
+
57
+ let invokedContract: xdr.InvokeContractArgs;
58
+
59
+ try {
60
+ invokedContract = hostFn.func.invokeContract();
61
+ } catch (e) {
62
+ return null;
63
+ }
64
+
65
+ const contractId = StrKey.encodeContract(
66
+ invokedContract.contractAddress().contractId(),
67
+ );
68
+ const fnName = invokedContract
69
+ .functionName()
70
+ .toString() as SorobanTokenInterface;
71
+ const args = invokedContract.args();
72
+
73
+ if (
74
+ ![SorobanTokenInterface.transfer, SorobanTokenInterface.mint].includes(
75
+ fnName,
76
+ )
77
+ ) {
78
+ return null;
79
+ }
80
+
81
+ let opArgs: ArgsForTokenInvocation;
82
+
83
+ try {
84
+ opArgs = getArgsForTokenInvocation(fnName, args);
85
+ } catch (e) {
86
+ return null;
87
+ }
88
+
89
+ return {
90
+ fnName,
91
+ contractId,
92
+ ...opArgs,
93
+ };
94
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./formatTokenAmount";
2
+ export * from "./getInvocationDetails";
3
+ export * from "./getTokenInvocationArgs";
4
+ export * from "./parseTokenAmount";
5
+ export * from "./scValByType";
@@ -0,0 +1,33 @@
1
+ import { Soroban } from "@stellar/stellar-sdk";
2
+ import BigNumber from "bignumber.js";
3
+
4
+ /**
5
+ * https://github.com/stellar/js-stellar-base/blob/4b510113738aefb5decb31e2ae72c27da5dd7f5c/src/soroban.js
6
+ *
7
+ * Parse a token amount to use it on smart contract
8
+ *
9
+ * This function takes the display value and its decimals (if the token has
10
+ * any) and returns a string that'll be used within the smart contract.
11
+ *
12
+ * @param {string | number | BigNumber} amount the token amount you want to
13
+ * use in a smart contract which you've been displaying in a UI
14
+ * @param {number} decimals the number of decimal places expected in the
15
+ * display value (different than the "actual" number, because suffix zeroes
16
+ * might not be present)
17
+ *
18
+ * @returns {bigint} the whole number token amount represented by the display
19
+ * value with the decimal places shifted over
20
+ *
21
+ * @example
22
+ * const displayValueAmount = "123.4560"
23
+ * const parsedAmtForSmartContract = parseTokenAmount(displayValueAmount, 5);
24
+ * parsedAmtForSmartContract === "12345600"
25
+ */
26
+ export const parseTokenAmount = (
27
+ amount: string | number | BigNumber,
28
+ decimals: number,
29
+ ): bigint => {
30
+ const parsedAmount = Soroban.parseTokenAmount(amount.toString(), decimals);
31
+
32
+ return BigInt(parsedAmount.toString());
33
+ };
@@ -0,0 +1,97 @@
1
+ import { StrKey, scValToNative, xdr } from "@stellar/stellar-sdk";
2
+
3
+ /* eslint-disable jsdoc/require-returns-type */
4
+ /**
5
+ * This function attempts to convert smart contract (complex) value types
6
+ * to common/simpler types like string, array, buffer, JSON string, etc.
7
+ *
8
+ * @param {xdr.ScVal} scVal the smart contract (complex) value
9
+ *
10
+ *
11
+ * @returns the smart contract value converted to a common/simpler
12
+ * value like string, array, buffer, JSON string, etc.
13
+ *
14
+ * @example
15
+ * const accountAddress = xdr.ScVal.scvAddress(
16
+ * xdr.ScAddress.scAddressTypeAccount(
17
+ * xdr.PublicKey.publicKeyTypeEd25519(
18
+ * StrKey.decodeEd25519PublicKey("GBBM6BKZPEHWYO3E3YKREDPQXMS4VK35YLNU7NFBRI26RAN7GI5POFBB"),
19
+ * ),
20
+ * )
21
+ * ); ===> complex object
22
+ *
23
+ * scValByType(accountAddress) returns "GBBM6BKZPEHWYO3E3YKREDPQXMS4VK35YLNU7NFBRI26RAN7GI5POFBB"
24
+ */
25
+ export const scValByType = (scVal: xdr.ScVal) => {
26
+ switch (scVal.switch()) {
27
+ case xdr.ScValType.scvAddress(): {
28
+ const address = scVal.address();
29
+ const addressType = address.switch();
30
+ if (addressType.name === "scAddressTypeAccount") {
31
+ return StrKey.encodeEd25519PublicKey(address.accountId().ed25519());
32
+ }
33
+ return StrKey.encodeContract(address.contractId());
34
+ }
35
+
36
+ case xdr.ScValType.scvBool(): {
37
+ return scVal.b();
38
+ }
39
+
40
+ case xdr.ScValType.scvBytes(): {
41
+ return JSON.stringify(scVal.bytes().toJSON().data);
42
+ }
43
+
44
+ case xdr.ScValType.scvContractInstance(): {
45
+ const instance = scVal.instance();
46
+ return instance.executable().wasmHash()?.toString();
47
+ }
48
+
49
+ case xdr.ScValType.scvError(): {
50
+ const error = scVal.error();
51
+ return error.value();
52
+ }
53
+
54
+ case xdr.ScValType.scvTimepoint():
55
+ case xdr.ScValType.scvDuration():
56
+ case xdr.ScValType.scvI128():
57
+ case xdr.ScValType.scvI256():
58
+ case xdr.ScValType.scvI32():
59
+ case xdr.ScValType.scvI64():
60
+ case xdr.ScValType.scvU128():
61
+ case xdr.ScValType.scvU256():
62
+ case xdr.ScValType.scvU32():
63
+ case xdr.ScValType.scvU64(): {
64
+ return scValToNative(scVal).toString();
65
+ }
66
+
67
+ case xdr.ScValType.scvLedgerKeyNonce():
68
+ case xdr.ScValType.scvLedgerKeyContractInstance(): {
69
+ if (scVal.switch().name === "scvLedgerKeyNonce") {
70
+ const val = scVal.nonceKey().nonce();
71
+ return val.toString();
72
+ }
73
+ return scVal.value();
74
+ }
75
+
76
+ case xdr.ScValType.scvVec():
77
+ case xdr.ScValType.scvMap(): {
78
+ return JSON.stringify(
79
+ scValToNative(scVal),
80
+ (_, val) => (typeof val === "bigint" ? val.toString() : val),
81
+ 2,
82
+ );
83
+ }
84
+
85
+ case xdr.ScValType.scvString():
86
+ case xdr.ScValType.scvSymbol(): {
87
+ const native = scValToNative(scVal);
88
+ if (native.constructor === "Uint8Array") {
89
+ return native.toString();
90
+ }
91
+ return native;
92
+ }
93
+
94
+ default:
95
+ return null;
96
+ }
97
+ };
@@ -0,0 +1,39 @@
1
+ import { xdr } from "@stellar/stellar-sdk";
2
+
3
+ // https://github.com/stellar/soroban-examples/blob/main/token/src/contract.rs
4
+ export enum SorobanTokenInterface {
5
+ transfer = "transfer",
6
+ mint = "mint",
7
+ }
8
+
9
+ export type ArgsForTokenInvocation = {
10
+ from: string;
11
+ to: string;
12
+ amount: bigint | number;
13
+ };
14
+
15
+ export type TokenInvocationArgs = ArgsForTokenInvocation & {
16
+ fnName: SorobanTokenInterface;
17
+ contractId: string;
18
+ };
19
+
20
+ export interface FnArgsInvoke {
21
+ type: "invoke";
22
+ fnName: string;
23
+ contractId: string;
24
+ args: xdr.ScVal[];
25
+ }
26
+
27
+ export interface FnArgsCreateWasm {
28
+ type: "wasm";
29
+ salt: string;
30
+ hash: string;
31
+ address: string;
32
+ }
33
+
34
+ export interface FnArgsCreateSac {
35
+ type: "sac";
36
+ asset: string;
37
+ }
38
+
39
+ export type InvocationArgs = FnArgsInvoke | FnArgsCreateWasm | FnArgsCreateSac;
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./Helpers";
2
+ export * from "./Types";