Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/all-ways-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@mysten/sui': minor
---

Add ExecutingSigner class
1 change: 1 addition & 0 deletions packages/typescript/src/cryptography/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export {
type ParsedKeypair,
type SignatureWithBytes,
Signer,
ExecutingSigner,
Keypair,
decodeSuiPrivateKey,
encodeSuiPrivateKey,
Expand Down
37 changes: 37 additions & 0 deletions packages/typescript/src/cryptography/keypair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export abstract class Signer {
transaction,
client,
}: SignAndExecuteOptions): Promise<Experimental_SuiClientTypes.TransactionResponse> {
transaction.setSenderIfNotSet(this.toSuiAddress());
const bytes = await transaction.build({ client });
const { signature } = await this.signTransaction(bytes);
const response = await client.core.executeTransaction({
Expand All @@ -109,6 +110,42 @@ export abstract class Signer {
abstract getPublicKey(): PublicKey;
}

export class ExecutingSigner extends Signer {
#client: ClientWithCoreApi;
#signer: Signer;

constructor({ signer, client }: { signer: Signer; client: ClientWithCoreApi }) {
super();

this.#client = client;
this.#signer = signer;
}

sign(bytes: Uint8Array) {
return this.#signer.sign(bytes);
}

getKeyScheme() {
return this.#signer.getKeyScheme();
}

getPublicKey() {
return this.#signer.getPublicKey();
}

async signAndExecuteTransaction({
transaction,
}: Omit<
SignAndExecuteOptions,
'client'
>): Promise<Experimental_SuiClientTypes.TransactionResponse> {
return this.#signer.signAndExecuteTransaction({
transaction,
client: this.#client,
});
}
}

export abstract class Keypair extends Signer {
/**
* This returns the Bech32 secret key string for this keypair.
Expand Down
42 changes: 42 additions & 0 deletions packages/typescript/test/e2e/executing-signer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { beforeEach, describe, expect, it } from 'vitest';

import { Transaction } from '../../src/transactions';
import { normalizeSuiObjectId } from '../../src/utils';
import { setup, TestToolbox } from './utils/setup';
import { ExecutingSigner } from '../../src/cryptography';

export const SUI_CLOCK_OBJECT_ID = normalizeSuiObjectId('0x6');

describe('ExecutingSigner', () => {
let toolbox: TestToolbox;

beforeEach(async () => {
toolbox = await setup();
});

it('executes without a client', async () => {
const tx = new Transaction();

tx.transferObjects([tx.splitCoins(tx.gas, [1])], toolbox.address());

const signer = new ExecutingSigner({
signer: toolbox.keypair,
client: toolbox.client,
});

const result = await signer.signAndExecuteTransaction({
transaction: tx,
});

expect(result.effects.status.success).toBe(true);

expect(
await toolbox.keypair
.getPublicKey()
.verifyTransaction(await tx.build(), result.signatures[0]),
).toBe(true);
});
});
Loading