Skip to content

Commit 3357a62

Browse files
authored
Merge pull request #5168 from BitGo/COIN-2362
feat(sdk-coin-apt): add wallet and address support
2 parents 31e4aeb + 7ac235e commit 3357a62

File tree

6 files changed

+222
-23
lines changed

6 files changed

+222
-23
lines changed

modules/sdk-coin-apt/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"dependencies": {
4343
"@bitgo/sdk-core": "^28.14.1",
4444
"@bitgo/statics": "^50.9.0",
45+
"@aptos-labs/ts-sdk": "^1.32.0",
4546
"bignumber.js": "^9.1.2"
4647
},
4748
"devDependencies": {

modules/sdk-coin-apt/src/apt.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {
22
BaseCoin,
33
BitGoBase,
4+
InvalidAddressError,
45
KeyPair,
6+
MPCAlgorithm,
57
ParsedTransaction,
68
ParseTransactionOptions,
79
SignedTransaction,
@@ -10,6 +12,8 @@ import {
1012
VerifyTransactionOptions,
1113
} from '@bitgo/sdk-core';
1214
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
15+
import { KeyPair as AptKeyPair } from './lib';
16+
import utils from './lib/utils';
1317

1418
export class Apt extends BaseCoin {
1519
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
@@ -46,28 +50,54 @@ export class Apt extends BaseCoin {
4650
return 'Aptos';
4751
}
4852

49-
verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
50-
throw new Error('Method not implemented.');
53+
/** @inheritDoc */
54+
supportsTss(): boolean {
55+
return true;
56+
}
57+
58+
getMPCAlgorithm(): MPCAlgorithm {
59+
return 'eddsa';
5160
}
5261

53-
isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
62+
allowsAccountConsolidations(): boolean {
63+
return true;
64+
}
65+
66+
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
5467
throw new Error('Method not implemented.');
5568
}
5669

70+
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
71+
const { address: newAddress } = params;
72+
73+
if (!this.isValidAddress(newAddress)) {
74+
throw new InvalidAddressError(`invalid address: ${newAddress}`);
75+
}
76+
return true;
77+
}
78+
5779
parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction> {
5880
throw new Error('Method not implemented.');
5981
}
6082

6183
generateKeyPair(seed?: Buffer): KeyPair {
62-
throw new Error('Method not implemented.');
84+
const keyPair = seed ? new AptKeyPair({ seed }) : new AptKeyPair();
85+
const keys = keyPair.getKeys();
86+
if (!keys.prv) {
87+
throw new Error('Missing prv in key generation.');
88+
}
89+
return {
90+
pub: keys.pub,
91+
prv: keys.prv,
92+
};
6393
}
6494

6595
isValidPub(pub: string): boolean {
66-
throw new Error('Method not implemented.');
96+
return utils.isValidPublicKey(pub);
6797
}
6898

6999
isValidAddress(address: string): boolean {
70-
throw new Error('Method not implemented.');
100+
return utils.isValidAddress(address);
71101
}
72102

73103
signTransaction(params: SignTransactionOptions): Promise<SignedTransaction> {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const APT_ADDRESS_LENGTH = 64;
2+
export const APT_TRANSACTION_ID_LENGTH = 64;
3+
export const APT_BLOCK_ID_LENGTH = 64;
4+
export const APT_SIGNATURE_LENGTH = 128;
Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
1-
import { DefaultKeys, Ed25519KeyPair } from '@bitgo/sdk-core';
1+
import { DefaultKeys, Ed25519KeyPair, KeyPairOptions } from '@bitgo/sdk-core';
2+
import utils from './utils';
23

34
export class KeyPair extends Ed25519KeyPair {
5+
/**
6+
* Public constructor. By default, creates a key pair with a random master seed.
7+
*
8+
* @param { KeyPairOptions } source Either a master seed, a private key, or a public key
9+
*/
10+
constructor(source?: KeyPairOptions) {
11+
super(source);
12+
}
13+
414
/** @inheritdoc */
515
getKeys(): DefaultKeys {
6-
throw new Error('Method not implemented.');
16+
const result: DefaultKeys = { pub: this.keyPair.pub };
17+
if (this.keyPair.prv) {
18+
result.prv = this.keyPair.prv;
19+
}
20+
return result;
721
}
822

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

1429
/** @inheritdoc */
1530
recordKeysFromPublicKeyInProtocolFormat(pub: string): DefaultKeys {
16-
throw new Error('Method not implemented.');
31+
if (!utils.isValidPublicKey(pub)) {
32+
throw new Error(`Invalid Public Key ${pub}`);
33+
}
34+
35+
return { pub };
1736
}
1837

1938
/** @inheritdoc */
2039
getAddress(): string {
21-
throw new Error('Method not implemented.');
40+
return utils.getAddressFromPublicKey(this.keyPair.pub);
2241
}
2342
}

modules/sdk-coin-apt/src/lib/utils.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
1-
import { BaseUtils } from '@bitgo/sdk-core';
1+
import { AuthenticationKey, Ed25519PublicKey } from '@aptos-labs/ts-sdk';
2+
import { BaseUtils, isValidEd25519PublicKey, isValidEd25519SecretKey } from '@bitgo/sdk-core';
3+
import { APT_ADDRESS_LENGTH, APT_BLOCK_ID_LENGTH, APT_SIGNATURE_LENGTH, APT_TRANSACTION_ID_LENGTH } from './constants';
24

35
export class Utils implements BaseUtils {
46
/** @inheritdoc */
57
isValidAddress(address: string): boolean {
6-
throw new Error('Method not implemented.');
8+
return this.isValidHex(address, APT_ADDRESS_LENGTH);
79
}
810

911
/** @inheritdoc */
1012
isValidBlockId(hash: string): boolean {
11-
throw new Error('Method not implemented.');
13+
return this.isValidHex(hash, APT_BLOCK_ID_LENGTH);
1214
}
1315

1416
/** @inheritdoc */
1517
isValidPrivateKey(key: string): boolean {
16-
throw new Error('Method not implemented.');
18+
return isValidEd25519SecretKey(key);
1719
}
1820

1921
/** @inheritdoc */
2022
isValidPublicKey(key: string): boolean {
21-
throw new Error('Method not implemented.');
23+
return isValidEd25519PublicKey(key);
2224
}
2325

2426
/** @inheritdoc */
2527
isValidSignature(signature: string): boolean {
26-
throw new Error('Method not implemented.');
28+
return this.isValidHex(signature, APT_SIGNATURE_LENGTH);
2729
}
2830

2931
/** @inheritdoc */
3032
isValidTransactionId(txId: string): boolean {
31-
throw new Error('Method not implemented.');
33+
return this.isValidHex(txId, APT_TRANSACTION_ID_LENGTH);
34+
}
35+
36+
isValidHex(value: string, length: number) {
37+
const regex = new RegExp(`^(0x|0X)[a-fA-F0-9]{${length}}$`);
38+
return regex.test(value);
39+
}
40+
41+
getAddressFromPublicKey(publicKey: string): string {
42+
const aptosPublicKey = new Ed25519PublicKey(Buffer.from(publicKey, 'hex'));
43+
const authKey = AuthenticationKey.fromPublicKey({ publicKey: aptosPublicKey });
44+
const accountAddress = authKey.derivedAddress();
45+
return accountAddress.toString();
3246
}
3347
}
3448

0 commit comments

Comments
 (0)