Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk-coin-apt): add wallet and address support #5168

Merged
merged 1 commit into from
Nov 25, 2024
Merged
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
1 change: 1 addition & 0 deletions modules/sdk-coin-apt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"dependencies": {
"@bitgo/sdk-core": "^28.14.1",
"@bitgo/statics": "^50.9.0",
"@aptos-labs/ts-sdk": "^1.32.0",
"bignumber.js": "^9.1.2"
},
"devDependencies": {
Expand Down
42 changes: 36 additions & 6 deletions modules/sdk-coin-apt/src/apt.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
BaseCoin,
BitGoBase,
InvalidAddressError,
KeyPair,
MPCAlgorithm,
ParsedTransaction,
ParseTransactionOptions,
SignedTransaction,
Expand All @@ -10,6 +12,8 @@ import {
VerifyTransactionOptions,
} from '@bitgo/sdk-core';
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
import { KeyPair as AptKeyPair } from './lib';
import utils from './lib/utils';

export class Apt extends BaseCoin {
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
Expand Down Expand Up @@ -46,28 +50,54 @@ export class Apt extends BaseCoin {
return 'Aptos';
}

verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
throw new Error('Method not implemented.');
/** @inheritDoc */
supportsTss(): boolean {
return true;
}

getMPCAlgorithm(): MPCAlgorithm {
return 'eddsa';
}

isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
allowsAccountConsolidations(): boolean {
return true;
}

async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
throw new Error('Method not implemented.');
}

async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
const { address: newAddress } = params;

if (!this.isValidAddress(newAddress)) {
throw new InvalidAddressError(`invalid address: ${newAddress}`);
}
return true;
}
Comment on lines +70 to +77
Copy link
Contributor

Choose a reason for hiding this comment

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

isn't this method supposed to ensure that the address is an actual wallet address as opposed to an arbitrary address?


parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction> {
throw new Error('Method not implemented.');
}

generateKeyPair(seed?: Buffer): KeyPair {
throw new Error('Method not implemented.');
const keyPair = seed ? new AptKeyPair({ seed }) : new AptKeyPair();
const keys = keyPair.getKeys();
if (!keys.prv) {
throw new Error('Missing prv in key generation.');
}
return {
pub: keys.pub,
prv: keys.prv,
};
}

isValidPub(pub: string): boolean {
throw new Error('Method not implemented.');
return utils.isValidPublicKey(pub);
}

isValidAddress(address: string): boolean {
throw new Error('Method not implemented.');
return utils.isValidAddress(address);
}

signTransaction(params: SignTransactionOptions): Promise<SignedTransaction> {
Expand Down
4 changes: 4 additions & 0 deletions modules/sdk-coin-apt/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const APT_ADDRESS_LENGTH = 64;
export const APT_TRANSACTION_ID_LENGTH = 64;
export const APT_BLOCK_ID_LENGTH = 64;
export const APT_SIGNATURE_LENGTH = 128;
27 changes: 23 additions & 4 deletions modules/sdk-coin-apt/src/lib/keyPair.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,42 @@
import { DefaultKeys, Ed25519KeyPair } from '@bitgo/sdk-core';
import { DefaultKeys, Ed25519KeyPair, KeyPairOptions } from '@bitgo/sdk-core';
import utils from './utils';

export class KeyPair extends Ed25519KeyPair {
/**
* Public constructor. By default, creates a key pair with a random master seed.
*
* @param { KeyPairOptions } source Either a master seed, a private key, or a public key
*/
constructor(source?: KeyPairOptions) {
super(source);
}

/** @inheritdoc */
getKeys(): DefaultKeys {
throw new Error('Method not implemented.');
const result: DefaultKeys = { pub: this.keyPair.pub };
if (this.keyPair.prv) {
result.prv = this.keyPair.prv;
}
return result;
}

/** @inheritdoc */
recordKeysFromPrivateKeyInProtocolFormat(prv: string): DefaultKeys {
// We don't use private keys for APT since it's implemented for TSS.
throw new Error('Method not implemented.');
}

/** @inheritdoc */
recordKeysFromPublicKeyInProtocolFormat(pub: string): DefaultKeys {
throw new Error('Method not implemented.');
if (!utils.isValidPublicKey(pub)) {
throw new Error(`Invalid Public Key ${pub}`);
}

return { pub };
}

/** @inheritdoc */
getAddress(): string {
throw new Error('Method not implemented.');
return utils.getAddressFromPublicKey(this.keyPair.pub);
}
}
28 changes: 21 additions & 7 deletions modules/sdk-coin-apt/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,48 @@
import { BaseUtils } from '@bitgo/sdk-core';
import { AuthenticationKey, Ed25519PublicKey } from '@aptos-labs/ts-sdk';
import { BaseUtils, isValidEd25519PublicKey, isValidEd25519SecretKey } from '@bitgo/sdk-core';
import { APT_ADDRESS_LENGTH, APT_BLOCK_ID_LENGTH, APT_SIGNATURE_LENGTH, APT_TRANSACTION_ID_LENGTH } from './constants';

export class Utils implements BaseUtils {
/** @inheritdoc */
isValidAddress(address: string): boolean {
throw new Error('Method not implemented.');
return this.isValidHex(address, APT_ADDRESS_LENGTH);
}

/** @inheritdoc */
isValidBlockId(hash: string): boolean {
throw new Error('Method not implemented.');
return this.isValidHex(hash, APT_BLOCK_ID_LENGTH);
}

/** @inheritdoc */
isValidPrivateKey(key: string): boolean {
throw new Error('Method not implemented.');
return isValidEd25519SecretKey(key);
}

/** @inheritdoc */
isValidPublicKey(key: string): boolean {
throw new Error('Method not implemented.');
return isValidEd25519PublicKey(key);
}

/** @inheritdoc */
isValidSignature(signature: string): boolean {
throw new Error('Method not implemented.');
return this.isValidHex(signature, APT_SIGNATURE_LENGTH);
}

/** @inheritdoc */
isValidTransactionId(txId: string): boolean {
throw new Error('Method not implemented.');
return this.isValidHex(txId, APT_TRANSACTION_ID_LENGTH);
}

isValidHex(value: string, length: number) {
const regex = new RegExp(`^(0x|0X)[a-fA-F0-9]{${length}}$`);
return regex.test(value);
}

getAddressFromPublicKey(publicKey: string): string {
const aptosPublicKey = new Ed25519PublicKey(Buffer.from(publicKey, 'hex'));
const authKey = AuthenticationKey.fromPublicKey({ publicKey: aptosPublicKey });
const accountAddress = authKey.derivedAddress();
return accountAddress.toString();
}
}

Expand Down
Loading
Loading