diff --git a/wrappers/fedimint-ts/FedimintClient.ts b/wrappers/fedimint-ts/FedimintClient.ts index ca6cccb..81216c5 100644 --- a/wrappers/fedimint-ts/FedimintClient.ts +++ b/wrappers/fedimint-ts/FedimintClient.ts @@ -7,34 +7,34 @@ import type { DiscoverVersionRequest, DiscoverVersionResponse, JoinRequest, -} from "./types"; -import type { - AwaitInvoiceRequest, + LnInvoiceExternalPubkeyRequest, + LnInvoiceExternalPubkeyResponse, + LnInvoiceExternalPubkeyTweakedRequest, + LnInvoiceExternalPubkeyTweakedResponse, + LnClaimPubkeyReceiveRequest, + LnClaimPubkeyReceiveTweakedRequest, + LnAwaitInvoiceRequest, Gateway, LnInvoiceRequest, LnInvoiceResponse, LnPayRequest, LnPayResponse, -} from "./types"; -import type { - CombineRequest, - CombineResponse, - ReissueRequest, - ReissueResponse, - SpendRequest, - SpendResponse, - SplitRequest, - SplitResponse, - ValidateRequest, - ValidateResponse, -} from "./types"; -import type { - AwaitDepositRequest, - AwaitDepositResponse, - DepositAddressRequest, - DepositAddressResponse, - WithdrawRequest, - WithdrawResponse, + MintCombineRequest, + MintCombineResponse, + MintReissueRequest, + MintReissueResponse, + MintSpendRequest, + MintSpendResponse, + MintSplitRequest, + MintSplitResponse, + MintValidateRequest, + MintValidateResponse, + OnchainAwaitDepositRequest, + OnchainAwaitDepositResponse, + OnchainDepositAddressRequest, + OnchainDepositAddressResponse, + OnchainWithdrawRequest, + OnchainWithdrawResponse, } from "./types"; type FedimintResponse = Promise; @@ -266,6 +266,121 @@ class FedimintClient { ); }, + /** + * Creates a lightning invoice where the gateway contract locks the ecash to a specific pubkey + * Useful for creating invoices that pay to another user besides yourself + */ + createInvoiceForPubkey: async ( + pubkey: string, + amountMsat: number, + description: string, + expiryTime?: number, + federationId?: string + ): FedimintResponse => { + const request: LnInvoiceExternalPubkeyRequest = { + externalPubkey: pubkey, + amountMsat, + description, + expiryTime, + }; + + return await this.postWithId( + "/ln/invoice-external-pubkey", + request, + federationId + ); + }, + + /** + * Creates a lightning invoice where the gateway contract locks the ecash to a tweakedpubkey + * Fedimint-clientd tweaks the provided pubkey by the provided tweak, provide the pubkey and tweak + * Useful for creating invoices that pay to another user besides yourself + */ + createInvoiceForPubkeyTweak: async ( + pubkey: string, + tweak: number, + amountMsat: number, + description: string, + expiryTime?: number, + federationId?: string + ): FedimintResponse => { + const request: LnInvoiceExternalPubkeyTweakedRequest = { + externalPubkey: pubkey, + tweak, + amountMsat, + description, + expiryTime, + }; + + return await this.postWithId( + "/ln/invoice-external-pubkey-tweaked", + request, + federationId + ); + }, + + /** + * Claims a lightning contract that was paid to a specific pubkey + */ + claimPubkeyReceive: async ( + privateKey: string, + federationId?: string + ): FedimintResponse => { + const request: LnClaimPubkeyReceiveRequest = { privateKey }; + + return await this.postWithId( + "/ln/claim-external-receive", + request, + federationId + ); + }, + + /** + * Claims lightning contracts paid to tweaks of a pubkey + * Provide all the tweaks that were used to create the invoices + */ + claimPubkeyReceiveTweaked: async ( + privateKey: string, + tweaks: number[], + federationId?: string + ): FedimintResponse => { + const request: LnClaimPubkeyReceiveTweakedRequest = { + privateKey, + tweaks, + }; + + return await this.postWithId( + "/ln/claim-external-receive-tweaked", + request, + federationId + ); + }, + + /** + * Creates a lightning invoice where the gateway contract locks the ecash to a specific pubkey + * Useful for creating invoices that pay to another user besides yourself + */ + createInvoicePubkey: async ( + pubkey: string, + amountMsat: number, + description: string, + expiryTime?: number, + federationId?: string + ): FedimintResponse => { + const request: LnInvoiceExternalPubkeyRequest = { + externalPubkey: pubkey, + amountMsat, + description, + expiryTime, + }; + + return await this.postWithId( + "/ln/invoice-external-pubkey", + request, + federationId + ); + }, + /** * Waits for a lightning invoice to be paid */ @@ -273,7 +388,7 @@ class FedimintClient { operationId: string, federationId?: string ): FedimintResponse => { - const request: AwaitInvoiceRequest = { operationId }; + const request: LnAwaitInvoiceRequest = { operationId }; return await this.postWithId( "/ln/await-invoice", @@ -321,10 +436,10 @@ class FedimintClient { reissue: async ( notes: string, federationId?: string - ): FedimintResponse => { - const request: ReissueRequest = { notes }; + ): FedimintResponse => { + const request: MintReissueRequest = { notes }; - return await this.postWithId( + return await this.postWithId( "/mint/reissue", request, federationId @@ -340,15 +455,15 @@ class FedimintClient { timeout: number, includeInvite: boolean, federationId?: string - ): FedimintResponse => { - const request: SpendRequest = { + ): FedimintResponse => { + const request: MintSpendRequest = { amountMsat, allowOverpay, timeout, includeInvite, }; - return await this.postWithId( + return await this.postWithId( "/mint/spend", request, federationId @@ -361,10 +476,10 @@ class FedimintClient { validate: async ( notes: string, federationId?: string - ): FedimintResponse => { - const request: ValidateRequest = { notes }; + ): FedimintResponse => { + const request: MintValidateRequest = { notes }; - return await this.postWithId( + return await this.postWithId( "/mint/validate", request, federationId @@ -374,19 +489,21 @@ class FedimintClient { /** * Splits an ecash note into smaller notes */ - split: async (notes: string): FedimintResponse => { - const request: SplitRequest = { notes }; + split: async (notes: string): FedimintResponse => { + const request: MintSplitRequest = { notes }; - return await this.post("/mint/split", request); + return await this.post("/mint/split", request); }, /** * Combines ecash notes */ - combine: async (notesVec: string[]): FedimintResponse => { - const request: CombineRequest = { notesVec }; + combine: async ( + notesVec: string[] + ): FedimintResponse => { + const request: MintCombineRequest = { notesVec }; - return await this.post("/mint/combine", request); + return await this.post("/mint/combine", request); }, }; @@ -400,10 +517,10 @@ class FedimintClient { createDepositAddress: async ( timeout: number, federationId?: string - ): FedimintResponse => { - const request: DepositAddressRequest = { timeout }; + ): FedimintResponse => { + const request: OnchainDepositAddressRequest = { timeout }; - return await this.postWithId( + return await this.postWithId( "/wallet/deposit-address", request, federationId @@ -416,10 +533,10 @@ class FedimintClient { awaitDeposit: async ( operationId: string, federationId?: string - ): FedimintResponse => { - const request: AwaitDepositRequest = { operationId }; + ): FedimintResponse => { + const request: OnchainAwaitDepositRequest = { operationId }; - return await this.postWithId( + return await this.postWithId( "/wallet/await-deposit", request, federationId @@ -433,10 +550,10 @@ class FedimintClient { address: string, amountSat: number | "all", federationId?: string - ): FedimintResponse => { - const request: WithdrawRequest = { address, amountSat }; + ): FedimintResponse => { + const request: OnchainWithdrawRequest = { address, amountSat }; - return await this.postWithId( + return await this.postWithId( "/wallet/withdraw", request, federationId diff --git a/wrappers/fedimint-ts/bun.lockb b/wrappers/fedimint-ts/bun.lockb index 77f16d4..fab43d7 100755 Binary files a/wrappers/fedimint-ts/bun.lockb and b/wrappers/fedimint-ts/bun.lockb differ diff --git a/wrappers/fedimint-ts/package.json b/wrappers/fedimint-ts/package.json index f0929d0..0d68f44 100644 --- a/wrappers/fedimint-ts/package.json +++ b/wrappers/fedimint-ts/package.json @@ -10,14 +10,17 @@ "build": "tsc" }, "devDependencies": { - "bun-types": "latest", + "@types/secp256k1": "^4.0.6", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", + "bun-types": "latest", "eslint": "^8", "typescript": "^5.0.0" }, "dependencies": { + "crypto": "^1.0.1", "dotenv": "^16.3.1", - "fedimint-ts": "^0.2.7" + "fedimint-ts": "^0.2.7", + "secp256k1": "^5.0.0" } } diff --git a/wrappers/fedimint-ts/test.ts b/wrappers/fedimint-ts/test.ts index 5ab6d13..9002d4a 100644 --- a/wrappers/fedimint-ts/test.ts +++ b/wrappers/fedimint-ts/test.ts @@ -1,5 +1,7 @@ +import { randomBytes } from "crypto"; import { FedimintClientBuilder } from "./FedimintClient"; import dotenv from "dotenv"; +import * as secp256k1 from "secp256k1"; dotenv.config(); @@ -14,6 +16,25 @@ const logInputAndOutput = (input: any, output: any) => { console.log("--------------------"); }; +interface KeyPair { + privateKey: string; + publicKey: string; +} + +const newKeyPair = (): KeyPair => { + let privateKey: Buffer; + do { + privateKey = randomBytes(32); + } while (!secp256k1.privateKeyVerify(privateKey)); + + const publicKey = secp256k1.publicKeyCreate(privateKey); + + return { + privateKey: privateKey.toString("hex"), + publicKey: Buffer.from(publicKey).toString("hex"), + }; +}; + async function buildTestClient() { const baseUrl = process.env.BASE_URL || "http://127.0.0.1:3333"; const password = process.env.PASSWORD || "password"; @@ -29,6 +50,11 @@ async function buildTestClient() { async function main() { const fedimintClient = await buildTestClient(); + const keyPair = newKeyPair(); + console.log("Generated key pair: ", keyPair); + + return; + // ADMIN METHODS // `/v2/admin/config` logMethod("/v2/admin/config"); diff --git a/wrappers/fedimint-ts/types.ts b/wrappers/fedimint-ts/types.ts index 4cb4e97..262d413 100644 --- a/wrappers/fedimint-ts/types.ts +++ b/wrappers/fedimint-ts/types.ts @@ -48,16 +48,16 @@ interface OperationOutput { outcome?: any; } -interface DepositAddressRequest { +interface OnchainDepositAddressRequest { timeout: number; } -interface DepositAddressResponse { +interface OnchainDepositAddressResponse { operationId: string; address: string; } -interface AwaitDepositRequest { +interface OnchainAwaitDepositRequest { operationId: string; } @@ -85,16 +85,16 @@ interface AwaitDepositResponseConfirmed { out_idx: number; } -interface AwaitDepositResponse { +interface OnchainAwaitDepositResponse { status: { Confirmed: AwaitDepositResponseConfirmed } | { Failed: string }; } -interface WithdrawRequest { +interface OnchainWithdrawRequest { address: string; amountSat: number | "all"; } -interface WithdrawResponse { +interface OnchainWithdrawResponse { txid: string; feesSat: number; } @@ -110,7 +110,41 @@ interface LnInvoiceResponse { invoice: string; } -interface AwaitInvoiceRequest { +interface LnInvoiceExternalPubkeyRequest { + amountMsat: number; + description: string; + externalPubkey: string; + expiryTime?: number; +} + +interface LnInvoiceExternalPubkeyResponse { + operationId: string; + invoice: string; +} + +interface LnInvoiceExternalPubkeyTweakedRequest { + amountMsat: number; + description: string; + externalPubkey: string; + tweak: number; + expiryTime?: number; +} + +interface LnInvoiceExternalPubkeyTweakedResponse { + operationId: string; + invoice: string; +} + +interface LnClaimPubkeyReceiveRequest { + privateKey: string; +} + +interface LnClaimPubkeyReceiveTweakedRequest { + privateKey: string; + tweaks: number[]; +} + +interface LnAwaitInvoiceRequest { operationId: string; } @@ -127,7 +161,7 @@ interface LnPayResponse { fee: number; } -interface AwaitLnPayRequest { +interface LnAwaitPayRequest { operationId: string; } @@ -146,47 +180,47 @@ interface TieredMulti { [amount: number]: T[]; } -interface ReissueRequest { +interface MintReissueRequest { notes: string; } -interface ReissueResponse { +interface MintReissueResponse { amountMsat: number; } -interface SpendRequest { +interface MintSpendRequest { amountMsat: number; allowOverpay: boolean; timeout: number; includeInvite: boolean; } -interface SpendResponse { +interface MintSpendResponse { operation: string; notes: string; } -interface ValidateRequest { +interface MintValidateRequest { notes: string; } -interface ValidateResponse { +interface MintValidateResponse { amountMsat: number; } -interface SplitRequest { +interface MintSplitRequest { notes: string; } -interface SplitResponse { +interface MintSplitResponse { notes: Record; } -interface CombineRequest { +interface MintCombineRequest { notesVec: string[]; } -interface CombineResponse { +interface MintCombineResponse { notes: string; } @@ -201,28 +235,34 @@ export type { BackupRequest, ListOperationsRequest, OperationOutput, - DepositAddressRequest, - DepositAddressResponse, - AwaitDepositRequest, - AwaitDepositResponse, - WithdrawRequest, - WithdrawResponse, + OnchainDepositAddressRequest, + OnchainDepositAddressResponse, + OnchainAwaitDepositRequest, + OnchainAwaitDepositResponse, + OnchainWithdrawRequest, + OnchainWithdrawResponse, LnInvoiceRequest, LnInvoiceResponse, - AwaitInvoiceRequest, + LnInvoiceExternalPubkeyRequest, + LnInvoiceExternalPubkeyResponse, + LnInvoiceExternalPubkeyTweakedRequest, + LnInvoiceExternalPubkeyTweakedResponse, + LnClaimPubkeyReceiveRequest, + LnClaimPubkeyReceiveTweakedRequest, + LnAwaitInvoiceRequest, LnPayRequest, LnPayResponse, - AwaitLnPayRequest, + LnAwaitPayRequest, Gateway, SwitchGatewayRequest, - ReissueRequest, - ReissueResponse, - SpendRequest, - SpendResponse, - ValidateRequest, - ValidateResponse, - SplitRequest, - SplitResponse, - CombineRequest, - CombineResponse, + MintReissueRequest, + MintReissueResponse, + MintSpendRequest, + MintSpendResponse, + MintValidateRequest, + MintValidateResponse, + MintSplitRequest, + MintSplitResponse, + MintCombineRequest, + MintCombineResponse, };