diff --git a/src/contract/assembled_transaction.ts b/src/contract/assembled_transaction.ts index 8e95c3d8d..e4a9354f8 100644 --- a/src/contract/assembled_transaction.ts +++ b/src/contract/assembled_transaction.ts @@ -5,6 +5,7 @@ import { Address, BASE_FEE, Contract, + Keypair, Operation, SorobanDataBuilder, TransactionBuilder, @@ -15,6 +16,7 @@ import type { AssembledTransactionOptions, ClientOptions, MethodOptions, + SignTransaction, Tx, WalletError, XDR_BASE64, @@ -32,6 +34,7 @@ import { import { DEFAULT_TIMEOUT } from "./types"; import { SentTransaction } from "./sent_transaction"; import { Spec } from "./spec"; +import { basicNodeSigner } from './basic_node_signer'; /** @module contract */ @@ -682,7 +685,17 @@ export class AssembledTransaction { ); } - if (!signTransaction) { + // Check if signTransaction is a Keypair + let signFunction: SignTransaction | undefined; + + if (signTransaction instanceof Keypair) { + const keypair = signTransaction; + signFunction = basicNodeSigner(keypair, this.options.networkPassphrase).signTransaction; + } else if (typeof signTransaction === 'function') { + signFunction = signTransaction; + } + + if (!signFunction) { throw new AssembledTransaction.Errors.NoSigner( "You must provide a signTransaction function, either when calling " + "`signAndSend` or when initializing your Client" @@ -708,7 +721,10 @@ export class AssembledTransaction { .setTimeout(timeoutInSeconds) .build(); - const signOpts: Parameters>[1] = { + // const signOpts: Parameters>[1] = { + // networkPassphrase: this.options.networkPassphrase, + // }; + const signOpts: Parameters[1] = { networkPassphrase: this.options.networkPassphrase, }; @@ -716,7 +732,7 @@ export class AssembledTransaction { if (this.options.submit !== undefined) signOpts.submit = this.options.submit; if (this.options.submitUrl) signOpts.submitUrl = this.options.submitUrl; - const { signedTxXdr: signature, error } = await signTransaction( + const { signedTxXdr: signature, error } = await signFunction( this.built.toXDR(), signOpts, ); diff --git a/src/contract/types.ts b/src/contract/types.ts index 707a6f8fe..a320f99c7 100644 --- a/src/contract/types.ts +++ b/src/contract/types.ts @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { Memo, MemoType, Operation, Transaction, xdr } from "@stellar/stellar-base"; import type { Client } from "./client"; +import { Keypair } from "@stellar/stellar-base"; export type XDR_BASE64 = string; /** @@ -131,7 +132,7 @@ export type ClientOptions = { * * Matches signature of `signTransaction` from Freighter. */ - signTransaction?: SignTransaction; + signTransaction?: SignTransaction | Keypair; /** * A function to sign a specific auth entry for a transaction, using the * private key corresponding to the provided `publicKey`. This is only needed diff --git a/test/e2e/src/test-non-invoker-signing-by-contracts.js b/test/e2e/src/test-non-invoker-signing-by-contracts.js index 4cc911d6f..2bbf60654 100644 --- a/test/e2e/src/test-non-invoker-signing-by-contracts.js +++ b/test/e2e/src/test-non-invoker-signing-by-contracts.js @@ -31,6 +31,24 @@ describe("cross-contract auth", function () { async () => await this.context.tx.sign({ force: true }), ).to.not.throw(); }); + + it("signs transaction using Keypair", async function () { + const result = await this.context.tx.sign({ + signTransaction: this.context.keypair, + force: true, + }); + expect(result).to.be.undefined; + }); + + + it("signs transaction using basicNodeSigner", async function () { + const signer = contract.basicNodeSigner(this.context.keypair, "Standalone Network ; February 2017"); + const result = await this.context.tx.sign({ + signTransaction: signer.signTransaction, + force: true, + }); + expect(result).to.be.undefined; + }); }); describe("signAuthEntries with custom authorizeEntry", function () { diff --git a/test/e2e/src/util.js b/test/e2e/src/util.js index 7b4e160b3..c16ab7ebf 100644 --- a/test/e2e/src/util.js +++ b/test/e2e/src/util.js @@ -89,7 +89,9 @@ module.exports.generateFundedKeypair = generateFundedKeypair; */ async function clientFor(name, { keypair, contractId } = {}) { const internalKeypair = keypair ?? (await generateFundedKeypair()); - const signer = contract.basicNodeSigner(internalKeypair, networkPassphrase); + + // Pass the Keypair directly instead of using basicNodeSigner + const signer = internalKeypair; // Use Keypair directly if (contractId) { return { @@ -99,7 +101,7 @@ async function clientFor(name, { keypair, contractId } = {}) { rpcUrl, allowHttp: true, publicKey: internalKeypair.publicKey(), - ...signer, + signTransaction: signer, // Pass Keypair here }), contractId, keypair, @@ -118,7 +120,7 @@ async function clientFor(name, { keypair, contractId } = {}) { allowHttp: true, wasmHash: wasmHash, publicKey: internalKeypair.publicKey(), - ...signer, + signTransaction: signer, // Pass Keypair here }, ); const { result: client } = await deploy.signAndSend();