From 9f37dcf61b844f2929a51ca3b7ebe4ff1a101b66 Mon Sep 17 00:00:00 2001 From: Imamah-Zafar Date: Tue, 1 Aug 2023 18:06:55 +0500 Subject: [PATCH 1/5] serialize recipient array --- src/transactions/sendBtcTransaction.ts | 23 ++++++++++++++++++++--- src/transactions/types.ts | 8 ++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/transactions/sendBtcTransaction.ts b/src/transactions/sendBtcTransaction.ts index a9b154a..d9062eb 100644 --- a/src/transactions/sendBtcTransaction.ts +++ b/src/transactions/sendBtcTransaction.ts @@ -2,7 +2,17 @@ import type { Json } from 'jsontokens'; import { createUnsecuredToken } from 'jsontokens'; import { getDefaultProvider } from '../provider'; -import type { SendBtcTransactionOptions } from './types'; +import type { Recipient, SendBtcTransactionOptions, SerializedRecipient, SerializedSendBtcTransactionPayload } from './types'; + +const serializer = (recipient: Recipient[]): SerializedRecipient[] => { + return recipient.map((value) => { + const { address, amountSats } = value; + return { + address, + amountSats: amountSats.toString(), + }; + }); +}; export const sendBtcTransaction = async (options: SendBtcTransactionOptions) => { const { getProvider = getDefaultProvider } = options; @@ -11,7 +21,7 @@ export const sendBtcTransaction = async (options: SendBtcTransactionOptions) => throw new Error('No Bitcoin wallet installed'); } - const { recipients, senderAddress } = options.payload; + const { recipients, senderAddress, network, message } = options.payload; if (!recipients || recipients.length === 0) { throw new Error('At least one recipient is required'); } @@ -20,7 +30,14 @@ export const sendBtcTransaction = async (options: SendBtcTransactionOptions) => } try { - const request = createUnsecuredToken(options.payload as unknown as Json); + const serializedRecipients: SerializedRecipient[] = serializer(recipients); + const serialisedPayload: SerializedSendBtcTransactionPayload = { + network, + senderAddress, + message, + recipients: serializedRecipients, + }; + const request = createUnsecuredToken(serialisedPayload as unknown as Json); const response = await provider.sendBtcTransaction(request); options.onFinish?.(response); } catch (error) { diff --git a/src/transactions/types.ts b/src/transactions/types.ts index 548e3cb..532ba6d 100644 --- a/src/transactions/types.ts +++ b/src/transactions/types.ts @@ -5,12 +5,20 @@ export interface Recipient { amountSats: bigint; } +export type SerializedRecipient = Omit & { + amountSats: string; +}; + export interface SendBtcTransactionPayload extends RequestPayload { recipients: Recipient[]; senderAddress: string; message?: string; } +export type SerializedSendBtcTransactionPayload = Omit & { + recipients: SerializedRecipient[]; +}; + export type SendBtcTransactionResponse = string; export type SendBtcTransactionOptions = RequestOptions< From 2886e5f31b9b0f07f5bce8f6c3b81e467c557432 Mon Sep 17 00:00:00 2001 From: Imamah-Zafar Date: Tue, 1 Aug 2023 18:38:40 +0500 Subject: [PATCH 2/5] Fix AddressPurposes type --- src/addresses/types.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/addresses/types.ts b/src/addresses/types.ts index 883cd05..10a9c5d 100644 --- a/src/addresses/types.ts +++ b/src/addresses/types.ts @@ -1,19 +1,19 @@ import type { RequestOptions, RequestPayload } from '../types'; -export enum AddressPurpose { +export enum AddressPurposes { Ordinals = 'ordinals', Payment = 'payment', } export interface GetAddressPayload extends RequestPayload { - purposes: AddressPurpose[]; + purposes: AddressPurposes[]; message: string; } export interface Address { address: string; publicKey: string; - purpose: AddressPurpose; + purpose: AddressPurposes; } export interface GetAddressResponse { From 9ee1eb4fcb5b8f6c4b87a84f431760421557b6bf Mon Sep 17 00:00:00 2001 From: Imamah-Zafar Date: Wed, 2 Aug 2023 10:18:32 +0500 Subject: [PATCH 3/5] Revert AddressPurpose name change --- src/addresses/types.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/addresses/types.ts b/src/addresses/types.ts index 10a9c5d..883cd05 100644 --- a/src/addresses/types.ts +++ b/src/addresses/types.ts @@ -1,19 +1,19 @@ import type { RequestOptions, RequestPayload } from '../types'; -export enum AddressPurposes { +export enum AddressPurpose { Ordinals = 'ordinals', Payment = 'payment', } export interface GetAddressPayload extends RequestPayload { - purposes: AddressPurposes[]; + purposes: AddressPurpose[]; message: string; } export interface Address { address: string; publicKey: string; - purpose: AddressPurposes; + purpose: AddressPurpose; } export interface GetAddressResponse { From 3aa4935a2486368355c5b037cc1c4944fd35f6a4 Mon Sep 17 00:00:00 2001 From: Imamah-Zafar Date: Wed, 9 Aug 2023 10:53:25 +0500 Subject: [PATCH 4/5] Rename const --- src/transactions/sendBtcTransaction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transactions/sendBtcTransaction.ts b/src/transactions/sendBtcTransaction.ts index d9062eb..99500c4 100644 --- a/src/transactions/sendBtcTransaction.ts +++ b/src/transactions/sendBtcTransaction.ts @@ -31,13 +31,13 @@ export const sendBtcTransaction = async (options: SendBtcTransactionOptions) => try { const serializedRecipients: SerializedRecipient[] = serializer(recipients); - const serialisedPayload: SerializedSendBtcTransactionPayload = { + const serializedPayload: SerializedSendBtcTransactionPayload = { network, senderAddress, message, recipients: serializedRecipients, }; - const request = createUnsecuredToken(serialisedPayload as unknown as Json); + const request = createUnsecuredToken(serializedPayload as unknown as Json); const response = await provider.sendBtcTransaction(request); options.onFinish?.(response); } catch (error) { From db1b9f7f617e7ead3cd1a5ecbf1f42679a081e1e Mon Sep 17 00:00:00 2001 From: Imamah-Zafar Date: Wed, 9 Aug 2023 16:59:04 +0500 Subject: [PATCH 5/5] Check recipient type --- src/transactions/sendBtcTransaction.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/transactions/sendBtcTransaction.ts b/src/transactions/sendBtcTransaction.ts index 99500c4..e4e0ad8 100644 --- a/src/transactions/sendBtcTransaction.ts +++ b/src/transactions/sendBtcTransaction.ts @@ -2,7 +2,12 @@ import type { Json } from 'jsontokens'; import { createUnsecuredToken } from 'jsontokens'; import { getDefaultProvider } from '../provider'; -import type { Recipient, SendBtcTransactionOptions, SerializedRecipient, SerializedSendBtcTransactionPayload } from './types'; +import type { + Recipient, + SendBtcTransactionOptions, + SerializedRecipient, + SerializedSendBtcTransactionPayload, +} from './types'; const serializer = (recipient: Recipient[]): SerializedRecipient[] => { return recipient.map((value) => { @@ -25,6 +30,13 @@ export const sendBtcTransaction = async (options: SendBtcTransactionOptions) => if (!recipients || recipients.length === 0) { throw new Error('At least one recipient is required'); } + if ( + recipients.some( + (item) => typeof item.address !== 'string' || typeof item.amountSats !== 'bigint' + ) + ) { + throw new Error('Incorrect recipient format'); + } if (!senderAddress) { throw new Error('The sender address is required'); }