@algorandfoundation/algokit-utils 0.1.0 → 1.0.0-beta.2
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/LICENSE +21 -0
- package/README.md +31 -0
- package/dist/account.d.ts +87 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +148 -0
- package/dist/account.js.map +1 -0
- package/dist/algo-amount.d.ts +18 -0
- package/dist/algo-amount.d.ts.map +1 -0
- package/dist/algo-amount.js +31 -0
- package/dist/algo-amount.js.map +1 -0
- package/dist/algo-http-client-with-retry.d.ts +14 -0
- package/dist/algo-http-client-with-retry.d.ts.map +1 -0
- package/dist/algo-http-client-with-retry.js +62 -0
- package/dist/algo-http-client-with-retry.js.map +1 -0
- package/dist/algod-type.d.ts +124 -0
- package/dist/algod-type.d.ts.map +1 -0
- package/dist/algod-type.js +3 -0
- package/dist/algod-type.js.map +1 -0
- package/dist/app.d.ts +150 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +160 -0
- package/dist/app.js.map +1 -0
- package/dist/application-client.d.ts +1 -0
- package/dist/application-client.d.ts.map +1 -0
- package/dist/application-client.js +69 -0
- package/dist/application-client.js.map +1 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -0
- package/dist/deploy-app.d.ts +149 -0
- package/dist/deploy-app.d.ts.map +1 -0
- package/dist/deploy-app.js +418 -0
- package/dist/deploy-app.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer-lookup.d.ts +31 -0
- package/dist/indexer-lookup.d.ts.map +1 -0
- package/dist/indexer-lookup.js +96 -0
- package/dist/indexer-lookup.js.map +1 -0
- package/dist/indexer-type.d.ts +314 -0
- package/dist/indexer-type.d.ts.map +1 -0
- package/dist/indexer-type.js +25 -0
- package/dist/indexer-type.js.map +1 -0
- package/dist/localnet.d.ts +54 -0
- package/dist/localnet.d.ts.map +1 -0
- package/dist/localnet.js +121 -0
- package/dist/localnet.js.map +1 -0
- package/dist/network-client.d.ts +102 -0
- package/dist/network-client.d.ts.map +1 -0
- package/dist/network-client.js +182 -0
- package/dist/network-client.js.map +1 -0
- package/dist/package.json +20 -0
- package/dist/transaction.d.ts +147 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +274 -0
- package/dist/transaction.js.map +1 -0
- package/dist/transfer.d.ts +24 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transfer.js +33 -0
- package/dist/transfer.js.map +1 -0
- package/dist/urlTokenBaseHTTPClient.d.ts +41 -0
- package/dist/urlTokenBaseHTTPClient.d.ts.map +1 -0
- package/dist/urlTokenBaseHTTPClient.js +151 -0
- package/dist/urlTokenBaseHTTPClient.js.map +1 -0
- package/package.json +101 -12
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.isLocalNet = exports.getAlgoKmdClient = exports.getAlgoIndexerClient = exports.getAlgoClient = exports.getDefaultLocalNetConfig = exports.getAlgoNodeConfig = exports.getIndexerConfigFromEnvironment = exports.getAlgodConfigFromEnvironment = void 0;
|
|
27
|
+
const algosdk_1 = __importStar(require("algosdk"));
|
|
28
|
+
const algo_http_client_with_retry_1 = require("./algo-http-client-with-retry");
|
|
29
|
+
/** Retrieve the algod configuration from environment variables (expects to be called from a Node.js environment not algod-side) */
|
|
30
|
+
function getAlgodConfigFromEnvironment() {
|
|
31
|
+
if (!process || !process.env) {
|
|
32
|
+
throw new Error('Attempt to get default algod configuration from a non Node.js context; supply the config instead');
|
|
33
|
+
}
|
|
34
|
+
if (!process.env.ALGOD_SERVER) {
|
|
35
|
+
throw new Error('Attempt to get default algod configuration without specifying ALGOD_SERVER in the environment variables');
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
server: process.env.ALGOD_SERVER,
|
|
39
|
+
port: process.env.ALGOD_PORT,
|
|
40
|
+
token: process.env.ALGOD_TOKEN,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
exports.getAlgodConfigFromEnvironment = getAlgodConfigFromEnvironment;
|
|
44
|
+
/** Retrieve the indexer configuration from environment variables (expects to be called from a Node.js environment not algod-side) */
|
|
45
|
+
function getIndexerConfigFromEnvironment() {
|
|
46
|
+
if (!process || !process.env) {
|
|
47
|
+
throw new Error('Attempt to get default indexer configuration from a non Node.js context; supply the config instead');
|
|
48
|
+
}
|
|
49
|
+
if (!process.env.INDEXER_SERVER) {
|
|
50
|
+
throw new Error('Attempt to get default indexer configuration without specifying INDEXER_SERVER in the environment variables');
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
server: process.env.INDEXER_SERVER,
|
|
54
|
+
port: process.env.INDEXER_PORT,
|
|
55
|
+
token: process.env.INDEXER_TOKEN,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
exports.getIndexerConfigFromEnvironment = getIndexerConfigFromEnvironment;
|
|
59
|
+
/** Returns the Algorand configuration to point to the AlgoNode service
|
|
60
|
+
*
|
|
61
|
+
* @param network Which network to connect to - TestNet or MainNet
|
|
62
|
+
* @param config Which algod config to return - Algod or Indexer
|
|
63
|
+
*/
|
|
64
|
+
function getAlgoNodeConfig(network, config) {
|
|
65
|
+
return {
|
|
66
|
+
server: `https://${network}-${config === 'algod' ? 'api' : 'idx'}.algonode.cloud/`,
|
|
67
|
+
port: 443,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
exports.getAlgoNodeConfig = getAlgoNodeConfig;
|
|
71
|
+
/** Returns the Algorand configuration to point to the default LocalNet
|
|
72
|
+
*
|
|
73
|
+
* @param configOrPort Which algod config to return - algod, kmd, or indexer OR a port number
|
|
74
|
+
*/
|
|
75
|
+
function getDefaultLocalNetConfig(configOrPort) {
|
|
76
|
+
return {
|
|
77
|
+
server: `http://localhost`,
|
|
78
|
+
port: configOrPort === 'algod' ? 4001 : configOrPort === 'indexer' ? 8980 : configOrPort === 'kmd' ? 4002 : configOrPort,
|
|
79
|
+
token: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
exports.getDefaultLocalNetConfig = getDefaultLocalNetConfig;
|
|
83
|
+
function getAlgoTokenHeader(server, token, defaultHeader) {
|
|
84
|
+
// Purestake uses a slightly different API key header than the default
|
|
85
|
+
if (server.includes('purestake.io') && typeof token === 'string')
|
|
86
|
+
return { 'X-API-Key': token };
|
|
87
|
+
// Because we override the default HTTP Client construction (to get retries) we need to put a string token into the standard header ourselves
|
|
88
|
+
return typeof token === 'string' ? { [defaultHeader ?? 'X-Algo-API-Token']: token } : token ?? {};
|
|
89
|
+
}
|
|
90
|
+
/** Returns an algod SDK client that automatically retries on idempotent calls
|
|
91
|
+
*
|
|
92
|
+
* @param config The config if you want to override the default (getting config from process.env)
|
|
93
|
+
* @example Default (load from environment variables)
|
|
94
|
+
*
|
|
95
|
+
* ```
|
|
96
|
+
* // Uses process.env.ALGOD_SERVER, process.env.ALGOD_PORT and process.env.ALGOD_TOKEN
|
|
97
|
+
* // Automatically detects if you are using PureStake to switch in the right header name for ALGOD_TOKEN
|
|
98
|
+
* const algod = getAlgoClient()
|
|
99
|
+
* await algod.healthCheck().do()
|
|
100
|
+
* ```
|
|
101
|
+
* @example AlgoNode (testnet)
|
|
102
|
+
* ```
|
|
103
|
+
* const algod = getAlgoClient(getAlgoNodeConfig('testnet', 'algod'))
|
|
104
|
+
* await algod.healthCheck().do()
|
|
105
|
+
* ```
|
|
106
|
+
* @example AlgoNode (mainnet)
|
|
107
|
+
* ```
|
|
108
|
+
* const algod = getAlgoClient(getAlgoNodeConfig('mainnet', 'algod'))
|
|
109
|
+
* await algod.healthCheck().do()
|
|
110
|
+
* ```
|
|
111
|
+
* @example Custom (e.g. default local sandbox, although we recommend loading this into a .env and using the Default option instead)
|
|
112
|
+
* ```
|
|
113
|
+
* const algod = getAlgoClient({server: 'http://localhost', port: '4001', token: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'})
|
|
114
|
+
* await algod.healthCheck().do()
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
function getAlgoClient(config) {
|
|
118
|
+
const { token, server, port } = config ?? getAlgodConfigFromEnvironment();
|
|
119
|
+
const httpClientWithRetry = new algo_http_client_with_retry_1.AlgoHttpClientWithRetry(getAlgoTokenHeader(server, token), server, port);
|
|
120
|
+
return new algosdk_1.default.Algodv2(httpClientWithRetry, server);
|
|
121
|
+
}
|
|
122
|
+
exports.getAlgoClient = getAlgoClient;
|
|
123
|
+
/** Returns an indexer SDK client that automatically retries on idempotent calls
|
|
124
|
+
*
|
|
125
|
+
* @param config The config if you want to override the default (getting config from process.env)
|
|
126
|
+
* @example Default (load from environment variables)
|
|
127
|
+
*
|
|
128
|
+
* ```
|
|
129
|
+
* // Uses process.env.INDEXER_SERVER, process.env.INDEXER_PORT and process.env.INDEXER_TOKEN
|
|
130
|
+
* // Automatically detects if you are using PureStake to switch in the right header name for INDEXER_TOKEN
|
|
131
|
+
* const indexer = getAlgoIndexerClient()
|
|
132
|
+
* await indexer.makeHealthCheck().do()
|
|
133
|
+
* ```
|
|
134
|
+
* @example AlgoNode (testnet)
|
|
135
|
+
* ```
|
|
136
|
+
* const indexer = getAlgoIndexerClient(getAlgoNodeConfig('testnet', 'indexer'))
|
|
137
|
+
* await indexer.makeHealthCheck().do()
|
|
138
|
+
* ```
|
|
139
|
+
* @example AlgoNode (mainnet)
|
|
140
|
+
* ```
|
|
141
|
+
* const indexer = getAlgoIndexerClient(getAlgoNodeConfig('mainnet', 'indexer'))
|
|
142
|
+
* await indexer.makeHealthCheck().do()
|
|
143
|
+
* ```
|
|
144
|
+
* @example Custom (e.g. default local sandbox, although we recommend loading this into a .env and using the Default option instead)
|
|
145
|
+
* ```
|
|
146
|
+
* const indexer = getAlgoIndexerClient({server: 'http://localhost', port: '8980', token: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'})
|
|
147
|
+
* await indexer.makeHealthCheck().do()
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
function getAlgoIndexerClient(config) {
|
|
151
|
+
const { token, server, port } = config ?? getIndexerConfigFromEnvironment();
|
|
152
|
+
const httpClientWithRetry = new algo_http_client_with_retry_1.AlgoHttpClientWithRetry(getAlgoTokenHeader(server, token, 'X-Indexer-API-Token'), server, port);
|
|
153
|
+
return new algosdk_1.Indexer(httpClientWithRetry);
|
|
154
|
+
}
|
|
155
|
+
exports.getAlgoIndexerClient = getAlgoIndexerClient;
|
|
156
|
+
/**
|
|
157
|
+
* Returns a KMD SDK client that automatically retries on idempotent calls
|
|
158
|
+
*
|
|
159
|
+
* KMD client allows you to export private keys, which is useful to get the default account in a sandbox network.
|
|
160
|
+
*
|
|
161
|
+
* @param config The config if you want to override the default (getting config from process.env)
|
|
162
|
+
* @example Default (load from environment variables)
|
|
163
|
+
*
|
|
164
|
+
* ```
|
|
165
|
+
* // Uses process.env.ALGOD_SERVER, process.env.KMD_PORT (or if not specified: port 4002) and process.env.ALGOD_TOKEN
|
|
166
|
+
* const kmd = getAlgoKmdClient()
|
|
167
|
+
* ```
|
|
168
|
+
* @example Custom (e.g. default local sandbox, although we recommend loading this into a .env and using the Default option instead)
|
|
169
|
+
* ```
|
|
170
|
+
* const kmd = getAlgoKmdClient({server: 'http://localhost', port: '4002', token: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'})
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
function getAlgoKmdClient(config) {
|
|
174
|
+
const { token, server } = config ?? getAlgodConfigFromEnvironment();
|
|
175
|
+
// We can only use Kmd on the Sandbox otherwise it's not exposed so this makes some assumptions
|
|
176
|
+
// (e.g. same token and server as algod and port 4002 by default)
|
|
177
|
+
return new algosdk_1.Kmd(token, server, process?.env?.KMD_PORT ?? '4002');
|
|
178
|
+
}
|
|
179
|
+
exports.getAlgoKmdClient = getAlgoKmdClient;
|
|
180
|
+
var localnet_1 = require("./localnet");
|
|
181
|
+
Object.defineProperty(exports, "isLocalNet", { enumerable: true, get: function () { return localnet_1.isLocalNet; } });
|
|
182
|
+
//# sourceMappingURL=network-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-client.js","sourceRoot":"","sources":["../src/network-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"main": "index.js",
|
|
3
|
+
"types": "index.d.ts",
|
|
4
|
+
"name": "@algorandfoundation/algokit-utils",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"private": false,
|
|
7
|
+
"description": "A set of core Algorand utilities written in TypeScript and released via npm that make it easier to build solutions on Algorand.",
|
|
8
|
+
"author": "Algorand Foundation",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=16.0"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/**/*"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"algosdk": "^2.1.0",
|
|
18
|
+
"buffer": "^6.0.3"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import algosdk, { Account, Algodv2, LogicSigAccount, MultisigMetadata, SuggestedParams, Transaction } from 'algosdk';
|
|
2
|
+
import { AlgoAmount } from './algo-amount';
|
|
3
|
+
import { PendingTransactionResponse } from './algod-type';
|
|
4
|
+
/** Account wrapper that supports partial or full multisig signing */
|
|
5
|
+
export declare class MultisigAccount {
|
|
6
|
+
_params: algosdk.MultisigMetadata;
|
|
7
|
+
_signingAccounts: (algosdk.Account | SigningAccount)[];
|
|
8
|
+
_addr: string;
|
|
9
|
+
get params(): Readonly<algosdk.MultisigMetadata>;
|
|
10
|
+
get signingAccounts(): Readonly<(algosdk.Account | SigningAccount)[]>;
|
|
11
|
+
get addr(): Readonly<string>;
|
|
12
|
+
constructor(multisigParams: MultisigMetadata, signingAccounts: (Account | SigningAccount)[]);
|
|
13
|
+
sign(transaction: Transaction | Uint8Array): Uint8Array;
|
|
14
|
+
}
|
|
15
|
+
/** Account wrapper that supports a rekeyed account */
|
|
16
|
+
export declare class SigningAccount implements Account {
|
|
17
|
+
private _account;
|
|
18
|
+
private _sender;
|
|
19
|
+
/**
|
|
20
|
+
* Algorand address of the sender
|
|
21
|
+
*/
|
|
22
|
+
get addr(): Readonly<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Secret key belonging to the signer
|
|
25
|
+
*/
|
|
26
|
+
get sk(): Readonly<Uint8Array>;
|
|
27
|
+
/**
|
|
28
|
+
* Algorand account of the underlying signing account
|
|
29
|
+
*/
|
|
30
|
+
get signer(): Account;
|
|
31
|
+
/**
|
|
32
|
+
* Algorand account of the sender address and signer private key
|
|
33
|
+
*/
|
|
34
|
+
get sender(): Account;
|
|
35
|
+
constructor(account: Account, sender: string | undefined);
|
|
36
|
+
}
|
|
37
|
+
export type TransactionNote = Uint8Array | TransactionNoteData | Arc2TransactionNote;
|
|
38
|
+
export type TransactionNoteData = string | null | undefined | number | any[] | Record<string, any>;
|
|
39
|
+
/** ARC-0002 compatible transaction note components, @see https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0002.md */
|
|
40
|
+
export type Arc2TransactionNote = {
|
|
41
|
+
dAppName: string;
|
|
42
|
+
format: 'm' | 'j' | 'b' | 'u';
|
|
43
|
+
data: string;
|
|
44
|
+
};
|
|
45
|
+
/** Encodes a transaction note into a byte array ready to be included in an Algorand transaction.
|
|
46
|
+
*
|
|
47
|
+
* @param note The transaction note
|
|
48
|
+
* @returns the transaction note ready for inclusion in a transaction
|
|
49
|
+
*
|
|
50
|
+
* Case on the value of `data` this either either be:
|
|
51
|
+
* * `null` | `undefined`: `undefined`
|
|
52
|
+
* * `string`: The string value
|
|
53
|
+
* * Uint8Array: passthrough
|
|
54
|
+
* * Arc2TransactionNote object: ARC-0002 compatible transaction note
|
|
55
|
+
* * Else: The object/value converted into a JSON string representation
|
|
56
|
+
*/
|
|
57
|
+
export declare function encodeTransactionNote(note?: TransactionNote): Uint8Array | undefined;
|
|
58
|
+
/** The sending configuration for a transaction */
|
|
59
|
+
export interface SendTransactionParams {
|
|
60
|
+
/** Whether to skip signing and sending the transaction to the chain (default: transaction signed and sent to chain)
|
|
61
|
+
* (and instead just return the raw transaction, e.g. so you can add it to a group of transactions) */
|
|
62
|
+
skipSending?: boolean;
|
|
63
|
+
/** Whether to skip waiting for the submitted transaction (only relevant if `skipSending` is `false` or unset) */
|
|
64
|
+
skipWaiting?: boolean;
|
|
65
|
+
/** Whether to suppress log messages from transaction send, default: do not suppress */
|
|
66
|
+
suppressLog?: boolean;
|
|
67
|
+
/** The maximum fee that you are happy to pay (default: unbounded) - if this is set it's possible the transaction could get rejected during network congestion */
|
|
68
|
+
maxFee?: AlgoAmount;
|
|
69
|
+
/** The maximum number of rounds to wait for confirmation, only applies if `skipWaiting` is `undefined` or `false`, default: wait up to 5 rounds */
|
|
70
|
+
maxRoundsToWaitForConfirmation?: number;
|
|
71
|
+
}
|
|
72
|
+
/** The result of sending a transaction */
|
|
73
|
+
export interface SendTransactionResult {
|
|
74
|
+
/** The transaction */
|
|
75
|
+
transaction: Transaction;
|
|
76
|
+
/** The response if the transaction was sent and waited for */
|
|
77
|
+
confirmation?: PendingTransactionResponse;
|
|
78
|
+
}
|
|
79
|
+
export type SendTransactionFrom = Account | SigningAccount | LogicSigAccount | MultisigAccount;
|
|
80
|
+
/**
|
|
81
|
+
* Returns the public address of the given transaction sender.
|
|
82
|
+
* @param sender A transaction sender
|
|
83
|
+
* @returns The public address
|
|
84
|
+
*/
|
|
85
|
+
export declare const getSenderAddress: (sender: SendTransactionFrom) => string;
|
|
86
|
+
/** Signs and sends the given transaction to the chain
|
|
87
|
+
*
|
|
88
|
+
* @param algod An algod client
|
|
89
|
+
* @param transaction The unsigned transaction
|
|
90
|
+
* @param from The account to sign the transaction with: either an account with private key loaded or a logic signature account
|
|
91
|
+
* @param config The sending configuration for this transaction
|
|
92
|
+
*
|
|
93
|
+
* @returns An object with transaction (`transaction`) and (if `skipWaiting` is `false` or unset) confirmation (`confirmation`)
|
|
94
|
+
*/
|
|
95
|
+
export declare const sendTransaction: (algod: Algodv2, transaction: Transaction, from: SendTransactionFrom, sendParams?: SendTransactionParams) => Promise<SendTransactionResult>;
|
|
96
|
+
/** Defines an unsigned transaction that will appear in a group of transactions along with its signing information */
|
|
97
|
+
export interface TransactionToSign {
|
|
98
|
+
/** The unsigned transaction to sign and send */
|
|
99
|
+
transaction: Transaction;
|
|
100
|
+
/** The account to use to sign the transaction, either an account (with private key loaded) or a logic signature account */
|
|
101
|
+
signer: SendTransactionFrom;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Signs and sends a group of [up to 16](https://developer.algorand.org/docs/get-details/atomic_transfers/#create-transactions) transactions to the chain
|
|
105
|
+
*
|
|
106
|
+
* @param groupSend The group details to send, with:
|
|
107
|
+
* * `transactions`: The array of transactions to send along with their signing account
|
|
108
|
+
* * `sendParams`: The parameters to dictate how the group is sent
|
|
109
|
+
* @param algod An algod client
|
|
110
|
+
* @returns An object with group transaction ID (`groupTransactionId`) and (if `skipWaiting` is `false` or unset) confirmation (`confirmation`)
|
|
111
|
+
*/
|
|
112
|
+
export declare const sendGroupOfTransactions: (groupSend: {
|
|
113
|
+
transactions: TransactionToSign[];
|
|
114
|
+
sendParams?: Omit<Omit<SendTransactionParams, 'maxFee'>, 'skipSending'>;
|
|
115
|
+
}, algod: Algodv2) => Promise<{
|
|
116
|
+
groupId: string;
|
|
117
|
+
confirmations: PendingTransactionResponse[] | undefined;
|
|
118
|
+
txIds: string[];
|
|
119
|
+
}>;
|
|
120
|
+
/**
|
|
121
|
+
* Wait until the transaction is confirmed or rejected, or until `timeout`
|
|
122
|
+
* number of rounds have passed.
|
|
123
|
+
*
|
|
124
|
+
* @param algod An algod client
|
|
125
|
+
* @param transactionId The transaction ID to wait for
|
|
126
|
+
* @param timeout Maximum number of rounds to wait
|
|
127
|
+
*
|
|
128
|
+
* @return Pending transaction information
|
|
129
|
+
* @throws Throws an error if the transaction is not confirmed or rejected in the next `timeout` rounds
|
|
130
|
+
*/
|
|
131
|
+
export declare const waitForConfirmation: (algod: Algodv2, transactionId: string, timeout: number) => Promise<PendingTransactionResponse>;
|
|
132
|
+
/**
|
|
133
|
+
* Limit the acceptable fee to a defined amount of µALGOs.
|
|
134
|
+
* This also sets the transaction to be flatFee to ensure the transaction only succeeds at
|
|
135
|
+
* the estimated rate.
|
|
136
|
+
* @param transaction The transaction to cap
|
|
137
|
+
* @param maxAcceptableFee The maximum acceptable fee to pay
|
|
138
|
+
*/
|
|
139
|
+
export declare function capTransactionFee(transaction: algosdk.Transaction, maxAcceptableFee: AlgoAmount): void;
|
|
140
|
+
/**
|
|
141
|
+
* Returns suggested transaction parameters from algod unless some are already provided.
|
|
142
|
+
* @param params Optionally provide parameters to use
|
|
143
|
+
* @param algod Algod algod
|
|
144
|
+
* @returns The suggested transaction parameters
|
|
145
|
+
*/
|
|
146
|
+
export declare function getTransactionParams(params: SuggestedParams | undefined, algod: Algodv2): Promise<algosdk.SuggestedParams>;
|
|
147
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getTransactionParams = exports.capTransactionFee = exports.waitForConfirmation = exports.sendGroupOfTransactions = exports.sendTransaction = exports.getSenderAddress = exports.encodeTransactionNote = exports.SigningAccount = exports.MultisigAccount = void 0;
|
|
7
|
+
const algosdk_1 = __importDefault(require("algosdk"));
|
|
8
|
+
const buffer_1 = require("buffer");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
/** Account wrapper that supports partial or full multisig signing */
|
|
11
|
+
class MultisigAccount {
|
|
12
|
+
get params() {
|
|
13
|
+
return this._params;
|
|
14
|
+
}
|
|
15
|
+
get signingAccounts() {
|
|
16
|
+
return this._signingAccounts;
|
|
17
|
+
}
|
|
18
|
+
get addr() {
|
|
19
|
+
return this._addr;
|
|
20
|
+
}
|
|
21
|
+
constructor(multisigParams, signingAccounts) {
|
|
22
|
+
this._params = multisigParams;
|
|
23
|
+
this._signingAccounts = signingAccounts;
|
|
24
|
+
this._addr = algosdk_1.default.multisigAddress(multisigParams);
|
|
25
|
+
}
|
|
26
|
+
sign(transaction) {
|
|
27
|
+
let signedTxn = 'from' in transaction ? undefined : transaction;
|
|
28
|
+
for (const signer of this._signingAccounts) {
|
|
29
|
+
if (signedTxn) {
|
|
30
|
+
signedTxn = algosdk_1.default.appendSignMultisigTransaction(signedTxn, this._params, signer.sk).blob;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
signedTxn = algosdk_1.default.signMultisigTransaction(transaction, this._params, signer.sk).blob;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
37
|
+
return signedTxn;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.MultisigAccount = MultisigAccount;
|
|
41
|
+
/** Account wrapper that supports a rekeyed account */
|
|
42
|
+
class SigningAccount {
|
|
43
|
+
/**
|
|
44
|
+
* Algorand address of the sender
|
|
45
|
+
*/
|
|
46
|
+
get addr() {
|
|
47
|
+
return this._sender;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Secret key belonging to the signer
|
|
51
|
+
*/
|
|
52
|
+
get sk() {
|
|
53
|
+
return this._account.sk;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Algorand account of the underlying signing account
|
|
57
|
+
*/
|
|
58
|
+
get signer() {
|
|
59
|
+
return this._account;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Algorand account of the sender address and signer private key
|
|
63
|
+
*/
|
|
64
|
+
get sender() {
|
|
65
|
+
return {
|
|
66
|
+
addr: this._sender,
|
|
67
|
+
sk: this._account.sk,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
constructor(account, sender) {
|
|
71
|
+
this._account = account;
|
|
72
|
+
this._sender = sender ?? account.addr;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.SigningAccount = SigningAccount;
|
|
76
|
+
/** Encodes a transaction note into a byte array ready to be included in an Algorand transaction.
|
|
77
|
+
*
|
|
78
|
+
* @param note The transaction note
|
|
79
|
+
* @returns the transaction note ready for inclusion in a transaction
|
|
80
|
+
*
|
|
81
|
+
* Case on the value of `data` this either either be:
|
|
82
|
+
* * `null` | `undefined`: `undefined`
|
|
83
|
+
* * `string`: The string value
|
|
84
|
+
* * Uint8Array: passthrough
|
|
85
|
+
* * Arc2TransactionNote object: ARC-0002 compatible transaction note
|
|
86
|
+
* * Else: The object/value converted into a JSON string representation
|
|
87
|
+
*/
|
|
88
|
+
function encodeTransactionNote(note) {
|
|
89
|
+
if (note == null || typeof note === 'undefined') {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
else if (typeof note === 'object' && note.constructor === Uint8Array) {
|
|
93
|
+
return note;
|
|
94
|
+
}
|
|
95
|
+
else if (typeof note === 'object' && 'dAppName' in note) {
|
|
96
|
+
const arc2Payload = `${note.dAppName}:${note.format}${note.data}`;
|
|
97
|
+
const encoder = new TextEncoder();
|
|
98
|
+
return encoder.encode(arc2Payload);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const n = typeof note === 'string' ? note : JSON.stringify(note);
|
|
102
|
+
const encoder = new TextEncoder();
|
|
103
|
+
return encoder.encode(n);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.encodeTransactionNote = encodeTransactionNote;
|
|
107
|
+
/**
|
|
108
|
+
* Returns the public address of the given transaction sender.
|
|
109
|
+
* @param sender A transaction sender
|
|
110
|
+
* @returns The public address
|
|
111
|
+
*/
|
|
112
|
+
const getSenderAddress = function (sender) {
|
|
113
|
+
return 'addr' in sender ? sender.addr : sender.address();
|
|
114
|
+
};
|
|
115
|
+
exports.getSenderAddress = getSenderAddress;
|
|
116
|
+
/** Signs and sends the given transaction to the chain
|
|
117
|
+
*
|
|
118
|
+
* @param algod An algod client
|
|
119
|
+
* @param transaction The unsigned transaction
|
|
120
|
+
* @param from The account to sign the transaction with: either an account with private key loaded or a logic signature account
|
|
121
|
+
* @param config The sending configuration for this transaction
|
|
122
|
+
*
|
|
123
|
+
* @returns An object with transaction (`transaction`) and (if `skipWaiting` is `false` or unset) confirmation (`confirmation`)
|
|
124
|
+
*/
|
|
125
|
+
const sendTransaction = async function (algod, transaction, from, sendParams) {
|
|
126
|
+
const { skipSending, skipWaiting, maxFee, suppressLog, maxRoundsToWaitForConfirmation } = sendParams ?? {};
|
|
127
|
+
if (maxFee !== undefined) {
|
|
128
|
+
capTransactionFee(transaction, maxFee);
|
|
129
|
+
}
|
|
130
|
+
if (skipSending) {
|
|
131
|
+
return { transaction };
|
|
132
|
+
}
|
|
133
|
+
const signedTransaction = 'sk' in from
|
|
134
|
+
? transaction.signTxn(from.sk)
|
|
135
|
+
: 'lsig' in from
|
|
136
|
+
? algosdk_1.default.signLogicSigTransactionObject(transaction, from).blob
|
|
137
|
+
: from.sign(transaction);
|
|
138
|
+
await algod.sendRawTransaction(signedTransaction).do();
|
|
139
|
+
if (!suppressLog) {
|
|
140
|
+
config_1.AlgoKitConfig.logger.info(`Sent transaction ID ${transaction.txID()} ${transaction.type} from ${(0, exports.getSenderAddress)(from)}`);
|
|
141
|
+
}
|
|
142
|
+
let confirmation = undefined;
|
|
143
|
+
if (!skipWaiting) {
|
|
144
|
+
confirmation = await (0, exports.waitForConfirmation)(algod, transaction.txID(), maxRoundsToWaitForConfirmation ?? 5);
|
|
145
|
+
}
|
|
146
|
+
return { transaction, confirmation };
|
|
147
|
+
};
|
|
148
|
+
exports.sendTransaction = sendTransaction;
|
|
149
|
+
/**
|
|
150
|
+
* Signs and sends a group of [up to 16](https://developer.algorand.org/docs/get-details/atomic_transfers/#create-transactions) transactions to the chain
|
|
151
|
+
*
|
|
152
|
+
* @param groupSend The group details to send, with:
|
|
153
|
+
* * `transactions`: The array of transactions to send along with their signing account
|
|
154
|
+
* * `sendParams`: The parameters to dictate how the group is sent
|
|
155
|
+
* @param algod An algod client
|
|
156
|
+
* @returns An object with group transaction ID (`groupTransactionId`) and (if `skipWaiting` is `false` or unset) confirmation (`confirmation`)
|
|
157
|
+
*/
|
|
158
|
+
const sendGroupOfTransactions = async function (groupSend, algod) {
|
|
159
|
+
const { transactions, sendParams } = groupSend;
|
|
160
|
+
const transactionsToSend = transactions.map((t) => {
|
|
161
|
+
return t.transaction;
|
|
162
|
+
});
|
|
163
|
+
const group = algosdk_1.default.assignGroupID(transactionsToSend);
|
|
164
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
165
|
+
const groupId = buffer_1.Buffer.from(group[0].group).toString('base64');
|
|
166
|
+
if (!sendParams?.suppressLog) {
|
|
167
|
+
config_1.AlgoKitConfig.logger.info(`Sending group of transactions (${groupId})`, { transactionsToSend });
|
|
168
|
+
}
|
|
169
|
+
const signedTransactions = group.map((groupedTransaction, index) => {
|
|
170
|
+
const signer = transactions[index].signer;
|
|
171
|
+
return 'sk' in signer
|
|
172
|
+
? groupedTransaction.signTxn(signer.sk)
|
|
173
|
+
: 'lsig' in signer
|
|
174
|
+
? algosdk_1.default.signLogicSigTransactionObject(groupedTransaction, signer).blob
|
|
175
|
+
: signer.sign(groupedTransaction);
|
|
176
|
+
});
|
|
177
|
+
if (!sendParams?.suppressLog) {
|
|
178
|
+
config_1.AlgoKitConfig.logger.debug(`Signer IDs (${groupId})`, transactions.map((t) => (0, exports.getSenderAddress)(t.signer)));
|
|
179
|
+
config_1.AlgoKitConfig.logger.debug(`Transaction IDs (${groupId})`, transactionsToSend.map((t) => t.txID()));
|
|
180
|
+
}
|
|
181
|
+
// https://developer.algorand.org/docs/rest-apis/algod/v2/#post-v2transactions
|
|
182
|
+
const result = await algod.sendRawTransaction(signedTransactions).do();
|
|
183
|
+
if (!sendParams?.suppressLog) {
|
|
184
|
+
config_1.AlgoKitConfig.logger.info(`Group transaction (${groupId}) sent with ${transactionsToSend.length} transactions`);
|
|
185
|
+
}
|
|
186
|
+
let confirmations = undefined;
|
|
187
|
+
if (!sendParams?.skipWaiting) {
|
|
188
|
+
confirmations = await Promise.all(transactionsToSend.map(async (t) => await (0, exports.waitForConfirmation)(algod, t.txID(), sendParams?.maxRoundsToWaitForConfirmation ?? 5)));
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
groupId,
|
|
192
|
+
confirmations,
|
|
193
|
+
txIds: transactionsToSend.map((t) => t.txID()),
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
exports.sendGroupOfTransactions = sendGroupOfTransactions;
|
|
197
|
+
/**
|
|
198
|
+
* Wait until the transaction is confirmed or rejected, or until `timeout`
|
|
199
|
+
* number of rounds have passed.
|
|
200
|
+
*
|
|
201
|
+
* @param algod An algod client
|
|
202
|
+
* @param transactionId The transaction ID to wait for
|
|
203
|
+
* @param timeout Maximum number of rounds to wait
|
|
204
|
+
*
|
|
205
|
+
* @return Pending transaction information
|
|
206
|
+
* @throws Throws an error if the transaction is not confirmed or rejected in the next `timeout` rounds
|
|
207
|
+
*/
|
|
208
|
+
const waitForConfirmation = async function (algod, transactionId, timeout) {
|
|
209
|
+
if (timeout < 0) {
|
|
210
|
+
throw new Error(`Invalid timeout, received ${timeout}, expected > 0`);
|
|
211
|
+
}
|
|
212
|
+
// Get current round
|
|
213
|
+
const status = await algod.status().do();
|
|
214
|
+
if (status === undefined) {
|
|
215
|
+
throw new Error('Unable to get node status');
|
|
216
|
+
}
|
|
217
|
+
// Loop for up to `timeout` rounds looking for a confirmed transaction
|
|
218
|
+
const startRound = status['last-round'] + 1;
|
|
219
|
+
let currentRound = startRound;
|
|
220
|
+
while (currentRound < startRound + timeout) {
|
|
221
|
+
const pendingInfo = (await algod.pendingTransactionInformation(transactionId).do());
|
|
222
|
+
if (pendingInfo !== undefined) {
|
|
223
|
+
const confirmedRound = pendingInfo['confirmed-round'];
|
|
224
|
+
if (confirmedRound && confirmedRound > 0) {
|
|
225
|
+
return pendingInfo;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
const poolError = pendingInfo['pool-error'];
|
|
229
|
+
if (poolError != null && poolError.length > 0) {
|
|
230
|
+
// If there was a pool error, then the transaction has been rejected!
|
|
231
|
+
throw new Error(`Transaction ${transactionId} was rejected; pool error: ${poolError}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
await algod.statusAfterBlock(currentRound).do();
|
|
236
|
+
currentRound++;
|
|
237
|
+
}
|
|
238
|
+
throw new Error(`Transaction ${transactionId} not confirmed after ${timeout} rounds`);
|
|
239
|
+
};
|
|
240
|
+
exports.waitForConfirmation = waitForConfirmation;
|
|
241
|
+
/**
|
|
242
|
+
* Limit the acceptable fee to a defined amount of µALGOs.
|
|
243
|
+
* This also sets the transaction to be flatFee to ensure the transaction only succeeds at
|
|
244
|
+
* the estimated rate.
|
|
245
|
+
* @param transaction The transaction to cap
|
|
246
|
+
* @param maxAcceptableFee The maximum acceptable fee to pay
|
|
247
|
+
*/
|
|
248
|
+
function capTransactionFee(transaction, maxAcceptableFee) {
|
|
249
|
+
// If a flat fee hasn't already been defined
|
|
250
|
+
if (!transaction.flatFee) {
|
|
251
|
+
// Once a transaction has been constructed by algosdk, transaction.fee indicates what the total transaction fee
|
|
252
|
+
// Will be based on the current suggested fee-per-byte value.
|
|
253
|
+
if (transaction.fee > maxAcceptableFee.microAlgos) {
|
|
254
|
+
throw new Error(`Cancelled transaction due to high network congestion fees. Algorand suggested fees would cause this transaction to cost ${transaction.fee} µALGOs. Cap for this transaction is ${maxAcceptableFee.microAlgos} µALGOs.`);
|
|
255
|
+
}
|
|
256
|
+
else if (transaction.fee > algosdk_1.default.ALGORAND_MIN_TX_FEE) {
|
|
257
|
+
config_1.AlgoKitConfig.logger.warn(`Algorand network congestion fees are in effect. This transaction will incur a fee of ${transaction.fee} µALGOs.`);
|
|
258
|
+
}
|
|
259
|
+
// Now set the flat on the transaction. Otherwise the network may increase the fee above our cap and perform the transaction.
|
|
260
|
+
transaction.flatFee = true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
exports.capTransactionFee = capTransactionFee;
|
|
264
|
+
/**
|
|
265
|
+
* Returns suggested transaction parameters from algod unless some are already provided.
|
|
266
|
+
* @param params Optionally provide parameters to use
|
|
267
|
+
* @param algod Algod algod
|
|
268
|
+
* @returns The suggested transaction parameters
|
|
269
|
+
*/
|
|
270
|
+
async function getTransactionParams(params, algod) {
|
|
271
|
+
return params ?? (await algod.getTransactionParams().do());
|
|
272
|
+
}
|
|
273
|
+
exports.getTransactionParams = getTransactionParams;
|
|
274
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"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"}
|