near-api-ts 0.2.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.
Files changed (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/index.cjs +3222 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +838 -0
  6. package/dist/index.d.ts +838 -0
  7. package/dist/index.js +3169 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +44 -0
  10. package/src/_common/configs/constants.ts +23 -0
  11. package/src/_common/schemas/borsh/actions/addKey.ts +44 -0
  12. package/src/_common/schemas/borsh/actions/createAccount.ts +7 -0
  13. package/src/_common/schemas/borsh/actions/deleteAccount.ts +9 -0
  14. package/src/_common/schemas/borsh/actions/deleteKey.ts +11 -0
  15. package/src/_common/schemas/borsh/actions/deployContract.ts +9 -0
  16. package/src/_common/schemas/borsh/actions/deployGlobalContract.ts +24 -0
  17. package/src/_common/schemas/borsh/actions/functionCall.ts +12 -0
  18. package/src/_common/schemas/borsh/actions/signedDelegate.ts +13 -0
  19. package/src/_common/schemas/borsh/actions/stake.ts +12 -0
  20. package/src/_common/schemas/borsh/actions/transfer.ts +9 -0
  21. package/src/_common/schemas/borsh/actions/useGlobalContract.ts +23 -0
  22. package/src/_common/schemas/borsh/delegateAction.ts +41 -0
  23. package/src/_common/schemas/borsh/index.ts +3 -0
  24. package/src/_common/schemas/borsh/publicKey.ts +25 -0
  25. package/src/_common/schemas/borsh/signature.ts +25 -0
  26. package/src/_common/schemas/borsh/signedTransaction.ts +10 -0
  27. package/src/_common/schemas/borsh/transaction.ts +42 -0
  28. package/src/_common/schemas/valibot/common.ts +12 -0
  29. package/src/_common/schemas/valibot/cryptoHash.ts +12 -0
  30. package/src/_common/schemas/valibot/curveString.ts +23 -0
  31. package/src/_common/schemas/valibot/privateKey.ts +38 -0
  32. package/src/_common/schemas/valibot/publicKey.ts +33 -0
  33. package/src/_common/schemas/valibot/transaction.ts +42 -0
  34. package/src/_common/schemas/zod/common.ts +29 -0
  35. package/src/_common/transformers/contract.ts +11 -0
  36. package/src/_common/transformers/curveString.ts +27 -0
  37. package/src/_common/transformers/toBorshBytes/signedTransaction.ts +20 -0
  38. package/src/_common/transformers/toBorshBytes/transaction.ts +12 -0
  39. package/src/_common/transformers/toNative/actions/addKey.ts +34 -0
  40. package/src/_common/transformers/toNative/actions/createAccount.ts +5 -0
  41. package/src/_common/transformers/toNative/actions/deleteAccount.ts +12 -0
  42. package/src/_common/transformers/toNative/actions/deleteKey.ts +13 -0
  43. package/src/_common/transformers/toNative/actions/deployContract.ts +17 -0
  44. package/src/_common/transformers/toNative/actions/functionCall.ts +22 -0
  45. package/src/_common/transformers/toNative/actions/transfer.ts +13 -0
  46. package/src/_common/transformers/toNative/blockReference.ts +30 -0
  47. package/src/_common/transformers/toNative/publicKey.ts +8 -0
  48. package/src/_common/transformers/toNative/signature.ts +8 -0
  49. package/src/_common/transformers/toNative/signedTransaction.ts +13 -0
  50. package/src/_common/transformers/toNative/transaction.ts +67 -0
  51. package/src/_common/utils/common.ts +22 -0
  52. package/src/_common/utils/createCircularQueue.ts +46 -0
  53. package/src/_common/utils/createLinkedList.ts +30 -0
  54. package/src/_common/utils/snakeToCamelCase.ts +26 -0
  55. package/src/_common/utils/tokenConverter/convertTokensToUnits.ts +65 -0
  56. package/src/_common/utils/tokenConverter/convertUnitsToTokens.ts +71 -0
  57. package/src/_common/utils/tokenConverter/helpers.ts +26 -0
  58. package/src/client/createClient/account/getAccountKey.ts +51 -0
  59. package/src/client/createClient/account/getAccountKeys.ts +47 -0
  60. package/src/client/createClient/account/getAccountState.ts +65 -0
  61. package/src/client/createClient/account/helpers/transformKey.ts +36 -0
  62. package/src/client/createClient/block/getBlock.ts +24 -0
  63. package/src/client/createClient/contract/callContractReadFunction.ts +66 -0
  64. package/src/client/createClient/contract/getContractState.ts +60 -0
  65. package/src/client/createClient/createClient.ts +34 -0
  66. package/src/client/createClient/createSendRequest.ts +29 -0
  67. package/src/client/createClient/protocol/getGasPrice.ts +51 -0
  68. package/src/client/createClient/protocol/getProtocolConfig.ts +39 -0
  69. package/src/client/createClient/transaction/sendSignedTransaction.ts +31 -0
  70. package/src/client/presets/networks.ts +21 -0
  71. package/src/helpers/actionCreators/addFullAccessKey.ts +14 -0
  72. package/src/helpers/actionCreators/addFunctionCallKey.ts +20 -0
  73. package/src/helpers/actionCreators/createAccount.ts +5 -0
  74. package/src/helpers/actionCreators/deleteAccount.ts +11 -0
  75. package/src/helpers/actionCreators/deleteKey.ts +9 -0
  76. package/src/helpers/actionCreators/deployContract.ts +13 -0
  77. package/src/helpers/actionCreators/functionCall.ts +12 -0
  78. package/src/helpers/actionCreators/transfer.ts +9 -0
  79. package/src/helpers/crypto/getPublicKey.ts +59 -0
  80. package/src/helpers/crypto/getRandomPrivateKey.ts +19 -0
  81. package/src/helpers/crypto/getTransactionHash.ts +21 -0
  82. package/src/helpers/crypto/sign.ts +69 -0
  83. package/src/helpers/gas.ts +25 -0
  84. package/src/helpers/near.ts +118 -0
  85. package/src/index.ts +19 -0
  86. package/src/keyServices/memoryKeyService/createFindPrivateKey.ts +11 -0
  87. package/src/keyServices/memoryKeyService/createMemoryKeyService.ts +23 -0
  88. package/src/keyServices/memoryKeyService/createSignTransaction.ts +24 -0
  89. package/src/keyServices/memoryKeyService/parseKeySources.ts +49 -0
  90. package/src/signers/memorySigner/createMemorySigner.ts +35 -0
  91. package/src/signers/memorySigner/executors/executeTransaction.ts +30 -0
  92. package/src/signers/memorySigner/executors/helpers/getSignedTransaction.ts +32 -0
  93. package/src/signers/memorySigner/executors/signTransaction.ts +26 -0
  94. package/src/signers/memorySigner/keyPool/createFindKeyForTask.ts +27 -0
  95. package/src/signers/memorySigner/keyPool/createIsKeyForTaskExist.ts +22 -0
  96. package/src/signers/memorySigner/keyPool/createKeyPool.ts +37 -0
  97. package/src/signers/memorySigner/keyPool/getFullAccessKeyList.ts +39 -0
  98. package/src/signers/memorySigner/keyPool/getFunctionCallKeyList.ts +43 -0
  99. package/src/signers/memorySigner/keyPool/helpers/keyUtils.ts +13 -0
  100. package/src/signers/memorySigner/matcher/createMatcher.ts +42 -0
  101. package/src/signers/memorySigner/resolver/createResolver.ts +21 -0
  102. package/src/signers/memorySigner/state/createState.ts +27 -0
  103. package/src/signers/memorySigner/taskQueue/addTask/executeMultipleTransactions.ts +29 -0
  104. package/src/signers/memorySigner/taskQueue/addTask/executeTransaction.ts +28 -0
  105. package/src/signers/memorySigner/taskQueue/addTask/helpers/getSigningKeyPriority.ts +39 -0
  106. package/src/signers/memorySigner/taskQueue/addTask/signMultipleTransactions.ts +26 -0
  107. package/src/signers/memorySigner/taskQueue/addTask/signTransaction.ts +23 -0
  108. package/src/signers/memorySigner/taskQueue/createFindTaskForKey.ts +22 -0
  109. package/src/signers/memorySigner/taskQueue/createTaskQueue.ts +45 -0
  110. package/types/accountKey.ts +24 -0
  111. package/types/actions/addKey.ts +48 -0
  112. package/types/actions/createAccount.ts +9 -0
  113. package/types/actions/deleteAccount.ts +18 -0
  114. package/types/actions/deleteKey.ts +18 -0
  115. package/types/actions/deployContract.ts +19 -0
  116. package/types/actions/functionCall.ts +32 -0
  117. package/types/actions/transfer.ts +18 -0
  118. package/types/client/account/getAccountKey.ts +30 -0
  119. package/types/client/account/getAccountKeys.ts +28 -0
  120. package/types/client/account/getAccountState.ts +40 -0
  121. package/types/client/block/getBlock.ts +13 -0
  122. package/types/client/client.ts +52 -0
  123. package/types/client/contract/callContractReadFunction.ts +98 -0
  124. package/types/client/contract/getContractState.ts +33 -0
  125. package/types/client/protocol/getGasPrice.ts +16 -0
  126. package/types/client/protocol/getProtocolConfig.ts +17 -0
  127. package/types/client/transaction/sendSignedTransaction.ts +19 -0
  128. package/types/common.ts +79 -0
  129. package/types/contract.ts +13 -0
  130. package/types/crypto.ts +25 -0
  131. package/types/delegateAction.ts +0 -0
  132. package/types/keyServices/memoryKeyService.ts +26 -0
  133. package/types/signedTransaction.ts +14 -0
  134. package/types/signers/memorySigner.ts +59 -0
  135. package/types/transaction.ts +107 -0
  136. package/types/utils.ts +44 -0
@@ -0,0 +1,69 @@
1
+ import * as v from 'valibot';
2
+ import type { PrivateKey, Signature } from 'nat-types/crypto';
3
+ import type { Hex } from 'nat-types/common';
4
+ import { ed25519 } from '@noble/curves/ed25519';
5
+ import { secp256k1 } from '@noble/curves/secp256k1';
6
+ import {
7
+ fromCurveString,
8
+ toEd25519CurveString,
9
+ toSecp256k1CurveString,
10
+ } from '@common/transformers/curveString';
11
+ import {
12
+ BinarySecp256k1PrivateKeySchema,
13
+ BinaryEd25519PrivateKeySchema,
14
+ } from '@common/schemas/valibot/privateKey';
15
+ import { BinaryCryptoKeyLengths } from '@common/configs/constants';
16
+
17
+ const { Ed25519, Secp256k1 } = BinaryCryptoKeyLengths;
18
+
19
+ const getBinaryEd25519SecretKey = (u8PrivateKey: Uint8Array) =>
20
+ v
21
+ .parse(BinaryEd25519PrivateKeySchema, u8PrivateKey)
22
+ .slice(0, Ed25519.SecretKey);
23
+
24
+ const signByEd25519Key = (message: Hex, u8PrivateKey: Uint8Array) => {
25
+ const u8SecretKey = getBinaryEd25519SecretKey(u8PrivateKey);
26
+ const u8Signature = ed25519.sign(message, u8SecretKey);
27
+
28
+ return {
29
+ signature: toEd25519CurveString(u8Signature),
30
+ u8Signature,
31
+ };
32
+ };
33
+
34
+ const getBinarySecp256k1SecretKey = (u8PrivateKey: Uint8Array) =>
35
+ v
36
+ .parse(BinarySecp256k1PrivateKeySchema, u8PrivateKey)
37
+ .slice(0, Secp256k1.SecretKey);
38
+
39
+ const signBySecp256k1Key = (message: Hex, u8PrivateKey: Uint8Array) => {
40
+ const u8SecretKey = getBinarySecp256k1SecretKey(u8PrivateKey);
41
+ const signatureObj = secp256k1.sign(message, u8SecretKey);
42
+
43
+ const u8Signature = new Uint8Array([
44
+ ...signatureObj.toBytes(),
45
+ signatureObj.recovery,
46
+ ]);
47
+
48
+ return {
49
+ signature: toSecp256k1CurveString(u8Signature),
50
+ u8Signature,
51
+ };
52
+ };
53
+
54
+ type SignInput = {
55
+ message: Hex;
56
+ privateKey: PrivateKey;
57
+ };
58
+
59
+ type SignOutput = {
60
+ signature: Signature;
61
+ u8Signature: Uint8Array;
62
+ };
63
+
64
+ export const sign = ({ message, privateKey }: SignInput): SignOutput => {
65
+ const { curve, u8Data: u8PrivateKey } = fromCurveString(privateKey);
66
+ return curve === 'ed25519'
67
+ ? signByEd25519Key(message, u8PrivateKey)
68
+ : signBySecp256k1Key(message, u8PrivateKey);
69
+ };
@@ -0,0 +1,25 @@
1
+ import type { GasLimit, GasOption, GasInput, TeraGasInput } from 'nat-types/common';
2
+
3
+ const TeraCoefficient = 10n ** 12n;
4
+
5
+ export const gas = (gas: GasInput) => {
6
+ // TODO Validate
7
+ return {
8
+ gas: BigInt(gas),
9
+ teraGas: String(BigInt(gas) / TeraCoefficient), // We don't keep decimals here
10
+ };
11
+ };
12
+
13
+ export const teraGas = (teraGas: TeraGasInput) => {
14
+ // TODO Validate
15
+ return {
16
+ gas: BigInt(teraGas) * TeraCoefficient,
17
+ teraGas,
18
+ };
19
+ };
20
+
21
+ export const fromGasOption = (gasOption: GasOption): GasLimit => {
22
+ if ('teraGas' in gasOption) return teraGas(gasOption.teraGas);
23
+ if ('gas' in gasOption) return gas(gasOption.gas);
24
+ throw new Error('Invalid gas option');
25
+ };
@@ -0,0 +1,118 @@
1
+ import { convertTokensToUnits } from '@common/utils/tokenConverter/convertTokensToUnits';
2
+ import { convertUnitsToTokens } from '@common/utils/tokenConverter/convertUnitsToTokens';
3
+ import { NearDecimals } from '@common/configs/constants';
4
+ import { nodeInspectSymbol } from '@common/utils/common';
5
+ import type {
6
+ Units,
7
+ Tokens,
8
+ NearOption,
9
+ NearToken,
10
+ Near,
11
+ YoctoNear,
12
+ } from 'nat-types/common';
13
+ import type { InspectOptionsStylized } from 'node:util';
14
+
15
+ const cache = {
16
+ near: new WeakMap<NearToken, string>(),
17
+ yoctoNear: new WeakMap<NearToken, bigint>(),
18
+ };
19
+
20
+ /**
21
+ * We use it as a prototype for all new NearToken instances. It allows us to reuse
22
+ * these functions without creating a new fn instances every time we create a new NearToken
23
+ */
24
+ const nearTokenProto: ThisType<NearToken> = {
25
+ // Lazy getter - calculate the 'near' value only after the first direct access;
26
+ // save the result in the cache
27
+ get near(): Near {
28
+ const maybeValue = cache.near.get(this);
29
+ if (maybeValue) return maybeValue;
30
+ const value = convertUnitsToTokens(this.yoctoNear, NearDecimals);
31
+ cache.near.set(this, value);
32
+
33
+ return value;
34
+ },
35
+
36
+ get yoctoNear(): YoctoNear {
37
+ const maybeValue = cache.yoctoNear.get(this);
38
+ if (maybeValue) return maybeValue;
39
+
40
+ const value = convertTokensToUnits(this.near, NearDecimals);
41
+ cache.yoctoNear.set(this, value);
42
+
43
+ return value;
44
+ },
45
+
46
+ // TODO add support for NearToken and avoid creating a new instance if x is NearToken
47
+ add(x: NearOption): NearToken {
48
+ return yoctoNear(this.yoctoNear + fromNearOption(x).yoctoNear);
49
+ },
50
+
51
+ sub(x: NearOption): NearToken {
52
+ return yoctoNear(this.yoctoNear - fromNearOption(x).yoctoNear);
53
+ },
54
+
55
+ mul(x: NearOption): NearToken {
56
+ return yoctoNear(this.yoctoNear * fromNearOption(x).yoctoNear);
57
+ },
58
+
59
+ gt(x: NearOption): boolean {
60
+ return this.yoctoNear > fromNearOption(x).yoctoNear;
61
+ },
62
+
63
+ lt(x: NearOption): boolean {
64
+ return this.yoctoNear < fromNearOption(x).yoctoNear;
65
+ },
66
+
67
+ toString() {
68
+ return JSON.stringify({
69
+ near: this.near,
70
+ yoctoNear: this.yoctoNear.toString(),
71
+ });
72
+ },
73
+
74
+ // In Node.js, this allows you to see the near/yoctoNear getter values,
75
+ // which are not normally visible unless you access them directly.
76
+ // This does not work in the browser — there you can only see a getter’s value
77
+ // by explicitly expanding/clicking on it.
78
+ ...(nodeInspectSymbol && {
79
+ [nodeInspectSymbol as symbol](
80
+ this: NearToken,
81
+ _depth: number,
82
+ _opts: InspectOptionsStylized,
83
+ ) {
84
+ return { near: this.near, yoctoNear: this.yoctoNear };
85
+ },
86
+ }),
87
+ } as const;
88
+
89
+ export const yoctoNear = (units: Units): NearToken => {
90
+ // TODO validate units
91
+ const yoctoNear = BigInt(units);
92
+ const obj = Object.create(nearTokenProto) as NearToken;
93
+
94
+ Object.defineProperty(obj, 'yoctoNear', {
95
+ value: yoctoNear,
96
+ enumerable: true,
97
+ });
98
+
99
+ return Object.freeze(obj);
100
+ };
101
+
102
+ export const near = (tokens: Tokens): NearToken => {
103
+ // TODO validate tokens
104
+ const obj = Object.create(nearTokenProto) as NearToken;
105
+
106
+ Object.defineProperty(obj, 'near', {
107
+ value: tokens,
108
+ enumerable: true,
109
+ });
110
+
111
+ return Object.freeze(obj);
112
+ };
113
+
114
+ export const fromNearOption = (nearOption: NearOption): NearToken => {
115
+ if ('yoctoNear' in nearOption) return yoctoNear(nearOption.yoctoNear);
116
+ if ('near' in nearOption) return near(nearOption.near);
117
+ throw new Error('Invalid nearOption format');
118
+ };
package/src/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ // Client
2
+ export { createClient } from './client/createClient/createClient';
3
+ export { testnet, mainnet } from './client/presets/networks';
4
+ // Key Services
5
+ export { createMemoryKeyService } from './keyServices/memoryKeyService/createMemoryKeyService';
6
+ // Signers
7
+ export { createMemorySigner } from './signers/memorySigner/createMemorySigner';
8
+ // Action Creators
9
+ export { transfer } from './helpers/actionCreators/transfer';
10
+ export { createAccount } from './helpers/actionCreators/createAccount';
11
+ export { addFullAccessKey } from './helpers/actionCreators/addFullAccessKey';
12
+ export { addFunctionCallKey } from './helpers/actionCreators/addFunctionCallKey';
13
+ export { functionCall } from './helpers/actionCreators/functionCall';
14
+ export { deleteKey } from './helpers/actionCreators/deleteKey';
15
+ export { deleteAccount } from './helpers/actionCreators/deleteAccount';
16
+ export { deployContract } from './helpers/actionCreators/deployContract';
17
+ // Helpers
18
+ export { near, yoctoNear } from './helpers/near';
19
+ export { gas, teraGas } from './helpers/gas';
@@ -0,0 +1,11 @@
1
+ import type { KeyPairs } from 'nat-types/keyServices/memoryKeyService';
2
+ import type { PublicKey } from 'nat-types/crypto';
3
+
4
+ export const createFindPrivateKey =
5
+ (keyPairs: KeyPairs) => (publicKey: PublicKey) => {
6
+ const privateKey = keyPairs[publicKey];
7
+ if (keyPairs[publicKey]) return privateKey;
8
+ throw new Error(
9
+ `Cannot find a corresponding private key for '${publicKey}'`,
10
+ );
11
+ };
@@ -0,0 +1,23 @@
1
+ import { createSignTransaction } from './createSignTransaction';
2
+ import { parseKeySources } from './parseKeySources';
3
+ import { createFindPrivateKey } from './createFindPrivateKey';
4
+ import type {
5
+ Context,
6
+ MemoryKeyService,
7
+ CreateMemoryKeyServiceInput,
8
+ } from 'nat-types/keyServices/memoryKeyService';
9
+
10
+ export const createMemoryKeyService = async (
11
+ params: CreateMemoryKeyServiceInput,
12
+ ): Promise<MemoryKeyService> => {
13
+ const context: Context = {
14
+ keyPairs: parseKeySources(params),
15
+ } as Context;
16
+
17
+ context.findPrivateKey = createFindPrivateKey(context.keyPairs);
18
+
19
+ return {
20
+ signTransaction: createSignTransaction(context),
21
+ getKeyPairs: () => context.keyPairs,
22
+ };
23
+ };
@@ -0,0 +1,24 @@
1
+ import { getTransactionHash } from '../../helpers/crypto/getTransactionHash';
2
+ import { sign } from '../../helpers/crypto/sign';
3
+ import type {
4
+ Context,
5
+ SignTransaction,
6
+ } from 'nat-types/keyServices/memoryKeyService';
7
+
8
+ export const createSignTransaction =
9
+ (context: Context): SignTransaction =>
10
+ async (transaction) => {
11
+ // TODO Implement validation
12
+ const privateKey = context.findPrivateKey(transaction.signerPublicKey);
13
+
14
+ const { transactionHash, u8TransactionHash } =
15
+ getTransactionHash(transaction);
16
+
17
+ const { signature } = sign({ message: u8TransactionHash, privateKey });
18
+
19
+ return {
20
+ transaction,
21
+ transactionHash,
22
+ signature,
23
+ };
24
+ };
@@ -0,0 +1,49 @@
1
+ import { getPublicKey } from '../../helpers/crypto/getPublicKey';
2
+ import type {
3
+ KeyPairs,
4
+ KeySource,
5
+ CreateMemoryKeyServiceInput,
6
+ } from 'nat-types/keyServices/memoryKeyService';
7
+ import type { PrivateKey, PublicKey } from 'nat-types/crypto';
8
+
9
+ const parseKeySource = (
10
+ keySource: KeySource,
11
+ ): { publicKey: PublicKey; privateKey: PrivateKey } => {
12
+ if ('privateKey' in keySource) {
13
+ return {
14
+ publicKey: getPublicKey(keySource.privateKey),
15
+ privateKey: keySource.privateKey,
16
+ };
17
+ }
18
+
19
+ // TODO implement
20
+ if ('seedPhrase' in keySource) {
21
+ return {
22
+ publicKey: 'ed25519:213',
23
+ privateKey: 'ed25519:213',
24
+ };
25
+ }
26
+
27
+ throw new Error('Unknown keySource');
28
+ };
29
+
30
+ export const parseKeySources = (
31
+ params: CreateMemoryKeyServiceInput,
32
+ ): KeyPairs => {
33
+ if (params.keySource) {
34
+ const { publicKey, privateKey } = parseKeySource(params.keySource);
35
+ return { [publicKey]: privateKey };
36
+ }
37
+
38
+ if (params.keySources)
39
+ return Object.fromEntries(
40
+ params.keySources.map((keySource) => {
41
+ const { publicKey, privateKey } = parseKeySource(keySource);
42
+ return [publicKey, privateKey];
43
+ }),
44
+ );
45
+
46
+ throw new Error(
47
+ 'Cannot create MemoryKeyService - no private keys were found',
48
+ );
49
+ };
@@ -0,0 +1,35 @@
1
+ import { createKeyPool } from './keyPool/createKeyPool';
2
+ import { createTaskQueue } from './taskQueue/createTaskQueue';
3
+ import { createMatcher } from './matcher/createMatcher';
4
+ import { createResolver } from './resolver/createResolver';
5
+ import { createState } from './state/createState';
6
+ import { SignerTaskTtlMs } from '@common/configs/constants';
7
+ import type { CreateMemorySigner } from 'nat-types/signers/memorySigner';
8
+
9
+ export const createMemorySigner: CreateMemorySigner = async (args) => {
10
+ const context: any = {
11
+ signerAccountId: args.signerAccountId,
12
+ client: args.client,
13
+ keyService: args.keyService,
14
+ signingKeys: args?.keyPool?.signingKeys,
15
+ taskTtlMs: args?.queue?.taskTtlMs ?? SignerTaskTtlMs,
16
+ };
17
+
18
+ const [keyPool, state] = await Promise.all([
19
+ createKeyPool(context),
20
+ createState(context),
21
+ ]);
22
+
23
+ context.keyPool = keyPool;
24
+ context.state = state;
25
+ context.taskQueue = createTaskQueue(context);
26
+ context.matcher = createMatcher(context);
27
+ context.resolver = createResolver();
28
+
29
+ return {
30
+ executeTransaction: context.taskQueue.executeTransaction,
31
+ executeMultipleTransactions: context.taskQueue.executeeMultipleTransactions,
32
+ signTransaction: context.taskQueue.signTransaction,
33
+ signMultipleTransactions: context.taskQueue.signMultipleTransactions,
34
+ };
35
+ };
@@ -0,0 +1,30 @@
1
+ import { getSignedTransaction } from './helpers/getSignedTransaction';
2
+
3
+ export const executeTransaction = async (
4
+ signerContext: any,
5
+ task: any,
6
+ key: any,
7
+ ) => {
8
+ try {
9
+ const nextNonce = key.nonce + 1;
10
+
11
+ const signedTransaction = getSignedTransaction(
12
+ signerContext,
13
+ task,
14
+ key,
15
+ nextNonce,
16
+ );
17
+
18
+ const result = await signerContext.client.sendSignedTransaction({
19
+ signedTransaction,
20
+ });
21
+
22
+ key.incrementNonce();
23
+
24
+ signerContext.resolver.completeTask(task.taskId, {
25
+ result,
26
+ });
27
+ } catch (e) {
28
+ signerContext.resolver.completeTask(task.taskId, { error: e });
29
+ }
30
+ };
@@ -0,0 +1,32 @@
1
+ import { getTransactionHash } from '../../../../helpers/crypto/getTransactionHash';
2
+ import { sign } from '../../../../helpers/crypto/sign';
3
+ import type { SignedTransaction } from 'nat-types/signedTransaction';
4
+
5
+ export const getSignedTransaction = (
6
+ signerContext: any,
7
+ task: any,
8
+ key: any,
9
+ nextNonce: bigint,
10
+ ): SignedTransaction => {
11
+ const transaction = {
12
+ ...task.transactionIntent,
13
+ signerAccountId: signerContext.signerAccountId,
14
+ signerPublicKey: key.publicKey,
15
+ nonce: nextNonce,
16
+ blockHash: signerContext.state.getBlockHash(),
17
+ };
18
+
19
+ const { transactionHash, u8TransactionHash } =
20
+ getTransactionHash(transaction);
21
+
22
+ const { signature } = sign({
23
+ message: u8TransactionHash,
24
+ privateKey: key.privateKey,
25
+ });
26
+
27
+ return {
28
+ transaction,
29
+ transactionHash,
30
+ signature,
31
+ };
32
+ };
@@ -0,0 +1,26 @@
1
+ import { getSignedTransaction } from './helpers/getSignedTransaction';
2
+
3
+ export const signTransaction = async (
4
+ signerContext: any,
5
+ task: any,
6
+ key: any,
7
+ ) => {
8
+ try {
9
+ const nextNonce = key.nonce + 1;
10
+
11
+ const signedTransaction = getSignedTransaction(
12
+ signerContext,
13
+ task,
14
+ key,
15
+ nextNonce,
16
+ );
17
+
18
+ key.incrementNonce();
19
+
20
+ signerContext.resolver.completeTask(task.taskId, {
21
+ result: signedTransaction,
22
+ });
23
+ } catch (e) {
24
+ signerContext.resolver.completeTask(task.taskId, { error: e });
25
+ }
26
+ };
@@ -0,0 +1,27 @@
1
+ const findSigningKey = (keyPriority: any, keyList: any) => {
2
+ if (keyPriority.type === 'FullAccess') {
3
+ return keyList.fullAccess.find((key: any) => !key.isLocked);
4
+ }
5
+
6
+ // If keyType is FunctionCall - find the key which follows all criteria
7
+ return keyList.functionCall.find((key: any) => {
8
+ const isUnlocked = key.isLocked === false;
9
+
10
+ const isContractIdMatch =
11
+ key.contractAccountId === keyPriority.contractAccountId;
12
+
13
+ // No allowedFunctions means that the key can call every contract function
14
+ const isFnCallAllowed =
15
+ key.allowedFunctions === undefined ||
16
+ key.allowedFunctions.includes(keyPriority.calledFnName);
17
+
18
+ return isUnlocked && isContractIdMatch && isFnCallAllowed;
19
+ });
20
+ };
21
+
22
+ export const createFindKeyForTask = (keyList: any) => (task: any) => {
23
+ for (const keyPriority of task.signingKeyPriority) {
24
+ const key = findSigningKey(keyPriority, keyList);
25
+ if (key) return key;
26
+ }
27
+ };
@@ -0,0 +1,22 @@
1
+ const isKeyExist = (keyPriority: any, keyList: any) => {
2
+ // If exists at least 1 FA key - return true
3
+ if (keyPriority.type === 'FullAccess') return keyList.fullAccess.length > 0;
4
+
5
+ // If keyType is FunctionCall - find the key which follows all criteria
6
+ return keyList.functionCall.find((key: any) => {
7
+ const isContractIdMatch =
8
+ key.contractAccountId === keyPriority.contractAccountId;
9
+
10
+ // No allowedFunctions means that the key can call every contract function
11
+ const isFnCallAllowed =
12
+ key.allowedFunctions === undefined ||
13
+ key.allowedFunctions.includes(keyPriority.calledFnName);
14
+
15
+ return isContractIdMatch && isFnCallAllowed;
16
+ });
17
+ };
18
+
19
+ export const createIsKeyForTaskExist = (keyList: any) => (task: any) =>
20
+ task.signingKeyPriority.some((keyPriority: any) =>
21
+ isKeyExist(keyPriority, keyList),
22
+ );
@@ -0,0 +1,37 @@
1
+ import { createFindKeyForTask } from './createFindKeyForTask';
2
+ import { createIsKeyForTaskExist } from './createIsKeyForTaskExist';
3
+ import { getFullAccessKeyList } from './getFullAccessKeyList';
4
+ import { getFunctionCallKeyList } from './getFunctionCallKeyList';
5
+ import type { SignerContext } from 'nat-types/signers/memorySigner';
6
+ import type { AccountKey } from 'nat-types/accountKey';
7
+
8
+ const getAllowedSigningKeys = (
9
+ signerContext: SignerContext,
10
+ accountKeys: AccountKey[],
11
+ ) => {
12
+ if (!signerContext.signingKeys) return accountKeys;
13
+ const set = new Set(signerContext.signingKeys);
14
+ return accountKeys.filter((key) => set.has(key.publicKey));
15
+ };
16
+
17
+ export const createKeyPool = async (signerContext: SignerContext) => {
18
+ const { accountKeys } = await signerContext.client.getAccountKeys({
19
+ accountId: signerContext.signerAccountId,
20
+ });
21
+
22
+ // If the user want to handle all tasks only by a specific key - remove others
23
+ const filteredKeys = getAllowedSigningKeys(signerContext, accountKeys);
24
+
25
+ const keyList = {
26
+ fullAccess: getFullAccessKeyList(filteredKeys, signerContext),
27
+ functionCall: getFunctionCallKeyList(filteredKeys, signerContext),
28
+ };
29
+
30
+ if (keyList.fullAccess.length === 0 && keyList.functionCall.length === 0)
31
+ throw new Error('Cannot create a signer with no account keys');
32
+
33
+ return {
34
+ findKeyForTask: createFindKeyForTask(keyList),
35
+ isKeyForTaskExist: createIsKeyForTaskExist(keyList),
36
+ };
37
+ };
@@ -0,0 +1,39 @@
1
+ import {
2
+ createUnlock,
3
+ createLock,
4
+ createIncrementNonce,
5
+ } from './helpers/keyUtils';
6
+ import type { AccountKey, FullAccessKey } from 'nat-types/accountKey';
7
+ import type { SignerContext } from 'nat-types/signers/memorySigner';
8
+ import type { KeyPairs } from 'nat-types/keyServices/memoryKeyService';
9
+
10
+ const transformKey = (fullAccessKey: FullAccessKey, keyPairs: KeyPairs) => {
11
+ const { publicKey, nonce } = fullAccessKey;
12
+
13
+ const key: any = {
14
+ type: 'FullAccess',
15
+ publicKey,
16
+ privateKey: keyPairs[publicKey],
17
+ isLocked: false,
18
+ nonce,
19
+ };
20
+ key.lock = createLock(key);
21
+ key.unlock = createUnlock(key);
22
+ key.incrementNonce = createIncrementNonce(key);
23
+
24
+ return key;
25
+ };
26
+
27
+ export const getFullAccessKeyList = (
28
+ accountKeys: AccountKey[],
29
+ signerContext: SignerContext,
30
+ ) => {
31
+ const keyPairs = signerContext.keyService.getKeyPairs();
32
+
33
+ return accountKeys
34
+ .filter(
35
+ ({ publicKey, accessType }) =>
36
+ Object.hasOwn(keyPairs, publicKey) && accessType === 'FullAccess',
37
+ )
38
+ .map((key) => transformKey(key as FullAccessKey, keyPairs));
39
+ };
@@ -0,0 +1,43 @@
1
+ import {
2
+ createIncrementNonce,
3
+ createLock,
4
+ createUnlock,
5
+ } from './helpers/keyUtils';
6
+ import type { AccountKey, FunctionCallKey } from 'nat-types/accountKey';
7
+ import type { SignerContext } from 'nat-types/signers/memorySigner';
8
+ import type { KeyPairs } from 'nat-types/keyServices/memoryKeyService';
9
+
10
+ const transformKey = (functionCallKey: FunctionCallKey, keyPairs: KeyPairs) => {
11
+ const { publicKey, nonce, contractAccountId, allowedFunctions } =
12
+ functionCallKey;
13
+
14
+ const key: any = {
15
+ type: 'FunctionCall', // TODO Rename to accessType
16
+ publicKey,
17
+ privateKey: keyPairs[publicKey],
18
+ isLocked: false,
19
+ nonce,
20
+ contractAccountId,
21
+ allowedFunctions,
22
+ };
23
+
24
+ key.lock = createLock(key);
25
+ key.unlock = createUnlock(key);
26
+ key.incrementNonce = createIncrementNonce(key);
27
+
28
+ return key;
29
+ };
30
+
31
+ export const getFunctionCallKeyList = (
32
+ accountKeys: AccountKey[],
33
+ signerContext: SignerContext,
34
+ ) => {
35
+ const keyPairs = signerContext.keyService.getKeyPairs();
36
+
37
+ return accountKeys
38
+ .filter(
39
+ ({ publicKey, accessType }) =>
40
+ Object.hasOwn(keyPairs, publicKey) && accessType === 'FunctionCall',
41
+ )
42
+ .map((key) => transformKey(key as FunctionCallKey, keyPairs));
43
+ };
@@ -0,0 +1,13 @@
1
+ export const createLock = (key: any) => () => {
2
+ key.isLocked = true;
3
+ console.log('Key locked', key.publicKey);
4
+ };
5
+
6
+ export const createUnlock = (key: any) => () => {
7
+ key.isLocked = false;
8
+ console.log('Key unlocked', key.publicKey);
9
+ };
10
+
11
+ export const createIncrementNonce = (key: any) => () => {
12
+ key.nonce = key.nonce + 1;
13
+ };