Skip to content

Commit 4f25141

Browse files
committed
feat: signer updates
1 parent 7e1c6b5 commit 4f25141

File tree

1 file changed

+111
-20
lines changed

1 file changed

+111
-20
lines changed

packages/sdk/src/mintlayer-connect-sdk.ts

Lines changed: 111 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,43 @@ interface UtxoEntry {
152152
utxo: Utxo;
153153
}
154154

155-
type Utxo = {
156-
type: 'Transfer' | 'LockThenTransfer' | 'IssueNft';
155+
type BaseUtxo = {
157156
value: Value;
158157
destination: string;
159158
token_id?: string;
160-
data?: any; // split NFT utxo
161159
};
162160

161+
type TransferUtxo = BaseUtxo & {
162+
type: 'Transfer';
163+
};
164+
165+
type LockThenTransferUtxo = BaseUtxo & {
166+
type: 'LockThenTransfer';
167+
lock: {
168+
type: 'ForBlockCount' | 'UntilTime';
169+
content: string;
170+
};
171+
};
172+
173+
type IssueNftUtxo = {
174+
type: 'IssueNft';
175+
value: Value;
176+
destination: string;
177+
token_id?: string;
178+
data: {
179+
name: { hex: string; string: string };
180+
ticker: { hex: string; string: string };
181+
description: { hex: string; string: string };
182+
media_hash: { hex: string; string: string };
183+
media_uri: { hex: string; string: string };
184+
icon_uri: { hex: string; string: string };
185+
additional_metadata_uri: { hex: string; string: string };
186+
creator: string | null;
187+
};
188+
};
189+
190+
type Utxo = TransferUtxo | LockThenTransferUtxo | IssueNftUtxo;
191+
163192
type UtxoInput = {
164193
input: {
165194
index: number;
@@ -2701,7 +2730,21 @@ class Client {
27012730
});
27022731

27032732
tx.JSONRepresentation.outputs.forEach((output, index) => {
2704-
if (output.type === 'Transfer' || output.type === 'LockThenTransfer') {
2733+
if (output.type === 'Transfer') {
2734+
created.push({
2735+
outpoint: {
2736+
index,
2737+
source_type: SourceId.Transaction,
2738+
source_id: tx.transaction_id,
2739+
},
2740+
utxo: {
2741+
type: output.type,
2742+
value: output.value,
2743+
destination: output.destination,
2744+
},
2745+
});
2746+
}
2747+
if (output.type === 'LockThenTransfer') {
27052748
created.push({
27062749
outpoint: {
27072750
index,
@@ -2712,6 +2755,7 @@ class Client {
27122755
type: output.type,
27132756
value: output.value,
27142757
destination: output.destination,
2758+
lock: output.lock,
27152759
},
27162760
});
27172761
}
@@ -2784,10 +2828,14 @@ class Client {
27842828
}
27852829

27862830
export class TransactionSigner {
2787-
private key: Uint8Array[];
2831+
private keys: Record<string, Uint8Array>;
27882832

2789-
constructor(privateKey: Uint8Array[]) {
2790-
this.key = privateKey;
2833+
constructor(privateKeys: Record<string, Uint8Array>) {
2834+
this.keys = privateKeys;
2835+
}
2836+
2837+
private getPrivateKey(address: string): Uint8Array | undefined {
2838+
return this.keys[address];
27912839
}
27922840

27932841
private createSignature(tx: Transaction) {
@@ -2824,25 +2872,52 @@ export class TransactionSigner {
28242872
}
28252873
})
28262874

2827-
const optUtxos: any[] = []
2875+
const optUtxosArray: number[] = [];
2876+
28282877
for (let i = 0; i < optUtxos_.length; i++) {
2878+
const utxoBytes = optUtxos_[i];
28292879
if (tx.JSONRepresentation.inputs[i].input.input_type !== 'UTXO') {
2830-
optUtxos.push(0)
2831-
continue
2880+
optUtxosArray.push(0);
28322881
} else {
2833-
optUtxos.push(1)
2834-
optUtxos.push(...optUtxos_[i])
2835-
continue
2882+
if (!(utxoBytes instanceof Uint8Array)) {
2883+
throw new Error(`optUtxos_[${i}] is not a valid Uint8Array`);
2884+
}
2885+
optUtxosArray.push(1);
2886+
optUtxosArray.push(...utxoBytes);
28362887
}
28372888
}
28382889

2890+
const optUtxos = new Uint8Array(optUtxosArray);
2891+
28392892
const encodedWitnesses = tx.JSONRepresentation.inputs.map(
28402893
(input, index) => {
2841-
const address =
2842-
input?.utxo?.destination ||
2843-
input?.input?.authority ||
2844-
input?.input?.destination
2845-
const addressPrivateKey = addressesPrivateKeys[address]
2894+
let address: string | undefined = undefined;
2895+
2896+
if(input.input.input_type === 'UTXO') {
2897+
const utxoInput = input as UtxoInput;
2898+
address = utxoInput.utxo.destination;
2899+
}
2900+
2901+
if (input.input.input_type === 'AccountCommand') {
2902+
// @ts-ignore
2903+
address = input.input.authority;
2904+
}
2905+
2906+
if (input.input.input_type === 'AccountCommand' && input.input.command === 'FillOrder') {
2907+
address = input.input.destination;
2908+
}
2909+
2910+
if (address === undefined) {
2911+
throw new Error(`Address not found for input at index ${index}`);
2912+
}
2913+
2914+
const addressPrivateKey = this.getPrivateKey(address)
2915+
2916+
if (!addressPrivateKey) {
2917+
throw new Error(`Private key not found for address: ${address}`);
2918+
}
2919+
2920+
const transaction = this.hexToUint8Array(tx.HEXRepresentation_unsigned);
28462921

28472922
const witness = encode_witness(
28482923
SignatureHashType.ALL,
@@ -2861,9 +2936,25 @@ export class TransactionSigner {
28612936
return signature;
28622937
}
28632938

2939+
private hexToUint8Array(hex: string): Uint8Array {
2940+
if (hex.length % 2 !== 0) {
2941+
throw new Error("Hex string must have an even length");
2942+
}
2943+
2944+
const bytes = new Uint8Array(hex.length / 2);
2945+
for (let i = 0; i < hex.length; i += 2) {
2946+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
2947+
}
2948+
return bytes;
2949+
}
2950+
28642951
private encodeSignedTransaction(tx: Transaction, signature: Uint8Array): string {
2865-
const transaction_signed = encode_signed_transaction(tx.HEXRepresentation_unsigned, signature);
2866-
return transaction_signed;
2952+
const transaction_signed = encode_signed_transaction(
2953+
this.hexToUint8Array(tx.HEXRepresentation_unsigned),
2954+
signature
2955+
);
2956+
const transaction_signed_hex = transaction_signed.reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), '');
2957+
return transaction_signed_hex;
28672958
}
28682959

28692960
sign(tx: Transaction): string {

0 commit comments

Comments
 (0)