-
Notifications
You must be signed in to change notification settings - Fork 210
/
Copy pathsigner.ts
126 lines (109 loc) · 4.06 KB
/
signer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { encodeUnsignedSimulateTransaction, Transaction } from './transaction';
import Account from './types/account';
import { LogicSigAccount, signLogicSigTransactionObject } from './logicsig';
import { MultisigMetadata } from './types/multisig';
import { signMultisigTransaction, mergeMultisigTransactions } from './multisig';
/**
* This type represents a function which can sign transactions from an atomic transaction group.
* @param txnGroup - The atomic group containing transactions to be signed
* @param indexesToSign - An array of indexes in the atomic transaction group that should be signed
* @returns A promise which resolves an array of encoded signed transactions. The length of the
* array will be the same as the length of indexesToSign, and each index i in the array
* corresponds to the signed transaction from txnGroup[indexesToSign[i]]
*/
export type TransactionSigner = (
txnGroup: Transaction[],
indexesToSign: number[]
) => Promise<Uint8Array[]>;
/**
* Create a TransactionSigner that can sign transactions for the provided basic Account.
*/
export function makeBasicAccountTransactionSigner(
account: Account
): TransactionSigner {
return (txnGroup: Transaction[], indexesToSign: number[]) => {
const signed: Uint8Array[] = [];
for (const index of indexesToSign) {
signed.push(txnGroup[index].signTxn(account.sk));
}
return Promise.resolve(signed);
};
}
/**
* Create a TransactionSigner that can sign transactions for the provided LogicSigAccount.
*/
export function makeLogicSigAccountTransactionSigner(
account: LogicSigAccount
): TransactionSigner {
return (txnGroup: Transaction[], indexesToSign: number[]) => {
const signed: Uint8Array[] = [];
for (const index of indexesToSign) {
const { blob } = signLogicSigTransactionObject(txnGroup[index], account);
signed.push(blob);
}
return Promise.resolve(signed);
};
}
/**
* Create a TransactionSigner that can sign transactions for the provided Multisig account.
* @param msig - The Multisig account metadata
* @param sks - An array of private keys belonging to the msig which should sign the transactions.
*/
export function makeMultiSigAccountTransactionSigner(
msig: MultisigMetadata,
sks: Uint8Array[]
): TransactionSigner {
return (txnGroup: Transaction[], indexesToSign: number[]) => {
const signed: Uint8Array[] = [];
for (const index of indexesToSign) {
const txn = txnGroup[index];
const partialSigs: Uint8Array[] = [];
for (const sk of sks) {
const { blob } = signMultisigTransaction(txn, msig, sk);
partialSigs.push(blob);
}
if (partialSigs.length > 1) {
signed.push(mergeMultisigTransactions(partialSigs));
} else {
signed.push(partialSigs[0]);
}
}
return Promise.resolve(signed);
};
}
/**
* Create a makeEmptyTransactionSigner that does not specify any signer or
* signing capabilities. This should only be used to simulate transactions.
*/
export function makeEmptyTransactionSigner(): TransactionSigner {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return (txnGroup: Transaction[], indexesToSign: number[]) => {
const unsigned: Uint8Array[] = [];
for (const index of indexesToSign) {
unsigned.push(encodeUnsignedSimulateTransaction(txnGroup[index]));
}
return Promise.resolve(unsigned);
};
}
/** Represents an unsigned transactions and a signer that can authorize that transaction. */
export interface TransactionWithSigner {
/** An unsigned transaction */
txn: Transaction;
/** A transaction signer that can authorize txn */
signer: TransactionSigner;
}
/**
* Check if a value conforms to the TransactionWithSigner structure.
* @param value - The value to check.
* @returns True if an only if the value has the structure of a TransactionWithSigner.
*/
export function isTransactionWithSigner(
value: any
): value is TransactionWithSigner {
return (
typeof value === 'object' &&
Object.keys(value).length === 2 &&
typeof value.txn === 'object' &&
typeof value.signer === 'function'
);
}