@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/CHANGELOG.MD +8 -0
- package/README.md +80 -0
- package/babel.config.js +5 -0
- package/lib/Helpers/formatTokenAmount.d.ts +18 -0
- package/lib/Helpers/getInvocationDetails.d.ts +12 -0
- package/lib/Helpers/getTokenInvocationArgs.d.ts +14 -0
- package/lib/Helpers/index.d.ts +5 -0
- package/lib/Helpers/parseTokenAmount.d.ts +24 -0
- package/lib/Helpers/scValByType.d.ts +23 -0
- package/lib/Types/index.d.ts +31 -0
- package/lib/bundle.js +50321 -0
- package/lib/bundle.js.map +1 -0
- package/lib/bundle_browser.js +698 -0
- package/lib/bundle_browser.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/package.json +41 -0
- package/src/Helpers/formatTokenAmount.ts +23 -0
- package/src/Helpers/getInvocationDetails.ts +81 -0
- package/src/Helpers/getTokenInvocationArgs.ts +94 -0
- package/src/Helpers/index.ts +5 -0
- package/src/Helpers/parseTokenAmount.ts +33 -0
- package/src/Helpers/scValByType.ts +97 -0
- package/src/Types/index.ts +39 -0
- package/src/index.ts +2 -0
- package/test/helpers.test.ts +555 -0
- package/test/tsconfig.json +10 -0
- package/test/utils/index.ts +38 -0
- package/tsconfig.json +10 -0
- package/webpack.config.js +51 -0
package/lib/index.d.ts
ADDED
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,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