Skip to content

Commit

Permalink
[ts-sdk] Remove usage of Base64DataBuffer (#8259)
Browse files Browse the repository at this point in the history
Currently, we have one data representation for binary data:
`Base64DataBuffer`. However, our use-cases for the data vary quite a
bit, sometimes staying as binary, and sometimes ending up as a base64
string. This is the first step in creating a clear separation between
bytes (Uint8Array) and Base64 data (string). All serialization work is
now expected before calling into the APIs.

This is part of a larger effort towards getting data types a little more
correct to begin with (e.g. having the `signData()` method return
base64-encoded data), but I'm doing this incrementally.
  • Loading branch information
Jordan-Mysten authored Feb 15, 2023
1 parent daf1bf5 commit 629804d
Show file tree
Hide file tree
Showing 32 changed files with 135 additions and 240 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-adults-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mysten/sui.js": minor
---

Remove usage of `Base64DataBuffer`, and use `Uint8Array` instead.
7 changes: 2 additions & 5 deletions apps/explorer/src/components/validator/ValidatorMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { ArrowUpRight12 } from '@mysten/icons';
import { Base64DataBuffer, type MoveActiveValidator } from '@mysten/sui.js';
import { toB64, type MoveActiveValidator } from '@mysten/sui.js';
import { useMemo } from 'react';

import { StakeButton } from './StakeButton';
Expand All @@ -24,10 +24,7 @@ export function ValidatorMeta({ validatorData }: ValidatorMetaProps) {
const validatorName = useMemo(() => getName(metadata.name), [metadata]);

const validatorPublicKey = useMemo(
() =>
new Base64DataBuffer(
new Uint8Array(metadata.pubkey_bytes)
).toString(),
() => toB64(new Uint8Array(metadata.pubkey_bytes)),
[metadata]
);

Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/src/utils/getName.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { Base64DataBuffer } from '@mysten/sui.js';
import { fromB64 } from '@mysten/sui.js';

// TODO : Import from SDK
import { VALDIATOR_NAME } from '~/pages/validator/ValidatorDataTypes';
Expand All @@ -14,7 +14,7 @@ export function getName(rawName: string | number[]) {
if (Array.isArray(rawName)) {
name = String.fromCharCode(...rawName);
} else {
name = textDecoder.decode(new Base64DataBuffer(rawName).getData());
name = textDecoder.decode(fromB64(rawName));
if (!VALDIATOR_NAME.test(name)) {
name = rawName;
}
Expand Down
9 changes: 2 additions & 7 deletions apps/wallet/src/background/keyring/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@

import { normalizeSuiAddress } from '@mysten/sui.js';

import type {
SignaturePubkeyPair,
Keypair,
SuiAddress,
Base64DataBuffer,
} from '@mysten/sui.js';
import type { SignaturePubkeyPair, Keypair, SuiAddress } from '@mysten/sui.js';

export type AccountType = 'derived' | 'imported';
export type AccountSerialized = {
Expand Down Expand Up @@ -41,7 +36,7 @@ export class Account {
return this.#keypair.export();
}

async sign(data: Base64DataBuffer): Promise<SignaturePubkeyPair> {
async sign(data: Uint8Array): Promise<SignaturePubkeyPair> {
return {
signatureScheme: this.#keypair.getKeyScheme(),
// TODO(joyqvq): Remove once 0.25.0 is released.
Expand Down
6 changes: 3 additions & 3 deletions apps/wallet/src/background/keyring/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { Base64DataBuffer, Ed25519Keypair } from '@mysten/sui.js';
import { Ed25519Keypair, fromB64, toB64 } from '@mysten/sui.js';
import mitt from 'mitt';
import { throttle } from 'throttle-debounce';

Expand Down Expand Up @@ -246,15 +246,15 @@ export class Keyring {
);
}
const { signature, signatureScheme, pubKey } =
await account.sign(new Base64DataBuffer(data));
await account.sign(fromB64(data));
uiConnection.send(
createMessage<KeyringPayload<'signData'>>(
{
type: 'keyring',
method: 'signData',
return: {
signatureScheme,
signature: signature.toString(),
signature: toB64(signature),
pubKey: pubKey.toBase64(),
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { SignerWithProvider } from '@mysten/sui.js';

import type { BackgroundClient } from '.';
import type {
Base64DataBuffer,
Provider,
SignaturePubkeyPair,
SuiAddress,
Expand All @@ -31,7 +30,7 @@ export class BackgroundServiceSigner extends SignerWithProvider {
return this.#address;
}

signData(data: Base64DataBuffer): Promise<SignaturePubkeyPair> {
signData(data: Uint8Array): Promise<SignaturePubkeyPair> {
return this.#backgroundClient.signData(this.#address, data);
}

Expand Down
8 changes: 4 additions & 4 deletions apps/wallet/src/ui/app/background-client/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { Base64DataBuffer, publicKeyFromSerialized } from '@mysten/sui.js';
import { fromB64, publicKeyFromSerialized, toB64 } from '@mysten/sui.js';
import { lastValueFrom, map, take } from 'rxjs';

import { growthbook } from '../experimentation/feature-gating';
Expand Down Expand Up @@ -213,14 +213,14 @@ export class BackgroundClient {

public async signData(
address: SuiAddress,
data: Base64DataBuffer
data: Uint8Array
): Promise<SignaturePubkeyPair> {
return await lastValueFrom(
this.sendMessage(
createMessage<KeyringPayload<'signData'>>({
type: 'keyring',
method: 'signData',
args: { data: data.toString(), address },
args: { data: toB64(data), address },
})
).pipe(
take(1),
Expand All @@ -233,7 +233,7 @@ export class BackgroundClient {
payload.return;
return {
signatureScheme,
signature: new Base64DataBuffer(signature),
signature: fromB64(signature),
pubKey: publicKeyFromSerialized(
signatureScheme,
pubKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import {
Base64DataBuffer,
fromB64,
getCertifiedTransaction,
getTransactionEffects,
LocalTxnDataSerializer,
Expand Down Expand Up @@ -84,7 +84,7 @@ export const deserializeTxn = createAsyncThunk<
}
const signer = api.getSignerInstance(activeAddress, background);
const localSerializer = new LocalTxnDataSerializer(signer.provider);
const txnBytes = new Base64DataBuffer(serializedTxn);
const txnBytes = fromB64(serializedTxn);

//TODO: Error handling - either show the error or use the serialized txn
const deserializeTx =
Expand Down Expand Up @@ -170,7 +170,7 @@ export const respondToTransactionRequest = createAsyncThunk<
: undefined
);
} else if (txRequest.tx.type === 'serialized-move-call') {
const txBytes = new Base64DataBuffer(txRequest.tx.data);
const txBytes = fromB64(txRequest.tx.data);
response = await signer.signAndExecuteTransaction(txBytes);
} else {
throw new Error(
Expand Down
9 changes: 2 additions & 7 deletions apps/wallet/src/ui/app/staking/usePendingDelegation.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import {
is,
SuiObject,
type SuiAddress,
Base64DataBuffer,
} from '@mysten/sui.js';
import { fromB64, is, SuiObject, type SuiAddress } from '@mysten/sui.js';
import { type UseQueryResult } from '@tanstack/react-query';
import { useMemo } from 'react';

Expand Down Expand Up @@ -55,7 +50,7 @@ export function getName(rawName: string | number[]) {
if (Array.isArray(rawName)) {
name = String.fromCharCode(...rawName);
} else {
name = textDecoder.decode(new Base64DataBuffer(rawName).getData());
name = textDecoder.decode(fromB64(rawName));
if (!VALDIATOR_NAME.test(name)) {
name = rawName;
}
Expand Down
10 changes: 2 additions & 8 deletions sdk/typescript/src/cryptography/ed25519-keypair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

import nacl from 'tweetnacl';
import { Base64DataBuffer } from '../serialization/base64';
import type { ExportedKeypair, Keypair } from './keypair';
import { Ed25519PublicKey } from './ed25519-publickey';
import { SignatureScheme } from './publickey';
Expand Down Expand Up @@ -116,13 +115,8 @@ export class Ed25519Keypair implements Keypair {
/**
* Return the signature for the provided data using Ed25519.
*/
signData(
data: Base64DataBuffer,
_useRecoverable: boolean = false,
): Base64DataBuffer {
return new Base64DataBuffer(
nacl.sign.detached(data.getData(), this.keypair.secretKey),
);
signData(data: Uint8Array, _useRecoverable: boolean = false): Uint8Array {
return nacl.sign.detached(data, this.keypair.secretKey);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions sdk/typescript/src/cryptography/keypair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

import { fromB64 } from '@mysten/bcs';
import { Base64DataBuffer } from '../serialization/base64';
import { Ed25519Keypair } from './ed25519-keypair';
import { PublicKey, SignatureScheme } from './publickey';
import { Secp256k1Keypair } from './secp256k1-keypair';
Expand All @@ -24,7 +23,7 @@ export interface Keypair {
/**
* Return the signature for the data
*/
signData(data: Base64DataBuffer, useRecoverable: boolean): Base64DataBuffer;
signData(data: Uint8Array, useRecoverable: boolean): Uint8Array;

/**
* Get the key scheme of the keypair: Secp256k1 or ED25519
Expand Down
9 changes: 4 additions & 5 deletions sdk/typescript/src/cryptography/secp256k1-keypair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

import * as secp from '@noble/secp256k1';
import { Base64DataBuffer } from '../serialization/base64';
import type { ExportedKeypair, Keypair } from './keypair';
import { PublicKey, SignatureScheme } from './publickey';
import { hmac } from '@noble/hashes/hmac';
Expand Down Expand Up @@ -119,8 +118,8 @@ export class Secp256k1Keypair implements Keypair {
/**
* Return the signature for the provided data.
*/
signData(data: Base64DataBuffer, useRecoverable: boolean): Base64DataBuffer {
const msgHash = sha256(data.getData());
signData(data: Uint8Array, useRecoverable: boolean): Uint8Array {
const msgHash = sha256(data);
// Starting from sui 0.25.0, sui accepts 64-byte nonrecoverable signature instead of 65-byte recoverable signature for Secp256k1.
// TODO(joyqvq): Remove recoverable signature support after 0.25.0 is released.
if (useRecoverable) {
Expand All @@ -131,13 +130,13 @@ export class Secp256k1Keypair implements Keypair {
var recoverable_sig = new Uint8Array(65);
recoverable_sig.set(Signature.fromDER(sig).toCompactRawBytes());
recoverable_sig.set([rec_id], 64);
return new Base64DataBuffer(recoverable_sig);
return recoverable_sig;
} else {
const sig = secp.signSync(msgHash, this.keypair.secretKey, {
canonical: true,
recovered: false,
});
return new Base64DataBuffer(Signature.fromDER(sig).toCompactRawBytes());
return Signature.fromDER(sig).toCompactRawBytes();
}
}

Expand Down
5 changes: 2 additions & 3 deletions sdk/typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export * from './providers/provider';
export * from './providers/json-rpc-provider';
export * from './providers/json-rpc-provider-with-cache';

export * from './serialization/base64';
export * from './serialization/hex';

export * from './signers/txn-data-serializers/rpc-txn-data-serializer';
export * from './signers/txn-data-serializers/txn-data-serializer';
export * from './signers/txn-data-serializers/local-txn-data-serializer';
Expand All @@ -30,4 +27,6 @@ export * from './utils/format';

export * from './framework';

export { fromB64, toB64 } from '@mysten/bcs';

export { is, assert } from 'superstruct';
5 changes: 2 additions & 3 deletions sdk/typescript/src/providers/json-rpc-provider-with-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
getTransactionEffects,
} from '../types';
import { JsonRpcProvider } from './json-rpc-provider';
import { Base64DataBuffer } from '../serialization/base64';
import { is } from 'superstruct';

export class JsonRpcProviderWithCache extends JsonRpcProvider {
Expand Down Expand Up @@ -62,9 +61,9 @@ export class JsonRpcProviderWithCache extends JsonRpcProvider {
// Transactions

async executeTransaction(
txnBytes: Base64DataBuffer,
txnBytes: Uint8Array,
signatureScheme: SignatureScheme,
signature: Base64DataBuffer,
signature: Uint8Array,
pubkey: PublicKey,
requestType: ExecuteTransactionRequestType = 'WaitForEffectsCert',
): Promise<SuiExecuteTransactionResponse> {
Expand Down
Loading

3 comments on commit 629804d

@vercel
Copy link

@vercel vercel bot commented on 629804d Feb 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

frenemies – ./dapps/frenemies

frenemies.sui.io
frenemies-mysten-labs.vercel.app
frenemies.vercel.app
frenemies-git-main-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 629804d Feb 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

wallet-adapter – ./sdk/wallet-adapter/example

sui-wallet-adapter.vercel.app
wallet-adapter-git-main-mysten-labs.vercel.app
wallet-adapter-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 629804d Feb 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

explorer – ./apps/explorer

explorer-topaz.vercel.app
explorer-git-main-mysten-labs.vercel.app
explorer.sui.io
explorer-mysten-labs.vercel.app

Please sign in to comment.