Skip to content

Commit

Permalink
feat: support polkadot (#367)
Browse files Browse the repository at this point in the history
  • Loading branch information
ByteZhang1024 authored Sep 29, 2024
1 parent f71d293 commit 90781b7
Show file tree
Hide file tree
Showing 14 changed files with 1,133 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
]
},
"scripts": {
"bootstrap": "lerna bootstrap",
"bootstrap": "npx patch-package && lerna bootstrap",
"build": "lerna run build",
"clean": "lerna clean --yes",
"clean-workspace": "yarn clean && lerna run clean",
Expand Down
7 changes: 6 additions & 1 deletion packages/connect-examples/expo-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
},
"dependencies": {
"@alephium/web3-wallet": "^1.5.2",
"@ckb-lumos/helpers": "^0.23.0",
"@expo/webpack-config": "^19.0.0",
"@nexajs/address": "^23.5.15",
"@nexajs/script": "^23.5.15",
"@noble/ed25519": "^2.1.0",
"@noble/hashes": "^1.3.3",
"@noble/secp256k1": "^1.7.1",
Expand All @@ -21,6 +24,7 @@
"@onekeyfe/hd-core": "^1.0.12-alpha.0",
"@onekeyfe/hd-web-sdk": "^1.0.12-alpha.0",
"@onekeyfe/react-native-ble-plx": "3.0.0",
"@polkadot/util-crypto": "13.1.1",
"@react-native-async-storage/async-storage": "1.21.0",
"@react-native-picker/picker": "2.6.1",
"@react-navigation/bottom-tabs": "^6.5.12",
Expand Down Expand Up @@ -75,7 +79,8 @@
"tamagui": "^1.90.2",
"text-encoding": "^0.7.0",
"tonweb": "^0.0.66",
"varint": "^6.0.0"
"varint": "^6.0.0",
"xrpl": "^4.0.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { SwitchInput } from '../../components/SwitchInput';
import { useRunnerTest } from '../../components/BaseTestRunner/useRunnerTest';
import useExportReport from '../../components/BaseTestRunner/useExportReport';
import { Button } from '../../components/ui/Button';
import { baseParams } from './baseParams';
import { ADDRESS_INDEX_MARK, baseParams, CHANGE_MARK, INDEX_MARK } from './baseParams';
import { replaceTemplate } from './data/utils';
import { ItemVerifyState } from '../../components/BaseTestRunner/Context/TestRunnerVerifyProvider';
import mockDevice from '../../utils/mockDevice';
Expand All @@ -25,6 +25,7 @@ type TestCaseDataType = {
address?: string;
path?: string;
variant?: string;
params?: any;
};

type MnemonicAddressTestCase = TestCase<TestCaseDataType[]>;
Expand All @@ -40,6 +41,14 @@ const testCase: MnemonicAddressTestCase = {
id: 'btcGetAddress',
method: 'btcGetAddress',
},
{
id: 'btcGetAddress-Neurai',
method: 'btcGetAddress',
params: {
path: `m/44'/1900'/${INDEX_MARK}'/${CHANGE_MARK}/${ADDRESS_INDEX_MARK}`,
coin: 'neurai',
},
},
{
id: 'evmGetAddress',
method: 'evmGetAddress',
Expand All @@ -48,6 +57,10 @@ const testCase: MnemonicAddressTestCase = {
id: 'alephiumGetAddress',
method: 'alephiumGetAddress',
},
{
id: 'algoGetAddress',
method: 'algoGetAddress',
},
{
id: 'dnxGetAddress',
method: 'dnxGetAddress',
Expand All @@ -56,6 +69,58 @@ const testCase: MnemonicAddressTestCase = {
id: 'tonGetAddress',
method: 'tonGetAddress',
},
{
id: 'nervosGetAddress',
method: 'nervosGetAddress',
},
{
id: 'nexaGetAddress',
method: 'nexaGetAddress',
},
{
id: 'polkadotGetAddress-polkadot',
method: 'polkadotGetAddress',
},
{
id: 'polkadotGetAddress-kusama',
method: 'polkadotGetAddress',
params: {
network: 'kusama',
prefix: '2',
},
},
{
id: 'polkadotGetAddress-astar',
method: 'polkadotGetAddress',
params: {
network: 'astar',
prefix: '5',
},
},
{
id: 'polkadotGetAddress-westend',
method: 'polkadotGetAddress',
params: {
network: 'westend',
prefix: '42',
},
},
{
id: 'polkadotGetAddress-manta',
method: 'polkadotGetAddress',
params: {
network: 'manta',
prefix: '77',
},
},
{
id: 'polkadotGetAddress-joystream',
method: 'polkadotGetAddress',
params: {
network: 'joystream',
prefix: '126',
},
},
{
id: 'scdoGetAddress',
method: 'scdoGetAddress',
Expand All @@ -64,6 +129,21 @@ const testCase: MnemonicAddressTestCase = {
id: 'suiGetAddress',
method: 'suiGetAddress',
},
{
id: 'xrpGetAddress',
method: 'xrpGetAddress',
},
{
id: 'cosmosGetAddress',
method: 'cosmosGetAddress',
},
{
id: 'cosmosGetAddress-cosmos',
method: 'cosmosGetAddress',
params: {
hrp: 'osmosis',
},
},
],
};

Expand All @@ -74,7 +154,7 @@ type ResultViewProps = {

function ResultView({ item, itemVerifyState }: ResultViewProps) {
const intl = useIntl();
const title = `${item?.method} ${item.path}`;
const title = `${item?.id} ${item.path}`;

return (
<>
Expand Down Expand Up @@ -125,9 +205,12 @@ function ExportReportView() {
return null;
}

function getRequestParams(method: string, index: string) {
// @ts-expect-error
const params = baseParams[method];
function getRequestParams(method: string, index: string, extraParams?: any) {
const params = {
// @ts-expect-error
...baseParams[method],
...extraParams,
};
let requestParams = {};

if (params?.addressParameters?.path) {
Expand Down Expand Up @@ -229,7 +312,7 @@ function ExecuteView() {
const { method } = item;

for (const variant of variantCase) {
const params = getRequestParams(method, variant);
const params = getRequestParams(method, variant, item.params);
console.log('======>>>>> passphraseStateList', params);
try {
// @ts-expect-error
Expand All @@ -252,16 +335,18 @@ function ExecuteView() {
};
currentTestCases.push(caseObject);
context.printLog(
`${intl.formatMessage({ id: 'message__fetch' })} ${
caseObject.path
} ${method} ${intl.formatMessage({
`${intl.formatMessage({ id: 'message__fetch' })} ${caseObject.path} ${
item.id
} ${intl.formatMessage({
id: 'message__address',
})} ${address}`
);
} catch (e) {
console.log('=====>>>>> error', e);
}
}

context.printLog('------------------------------------------');
}

console.log('currentTestCases', currentTestCases);
Expand All @@ -277,7 +362,7 @@ function ExecuteView() {
},
generateRequestParams: item => {
const requestParams = {
...getRequestParams(item.method, item.variant ?? '0'),
...getRequestParams(item.method, item.variant ?? '0', item.params),
// passphraseState: item.passphraseState,
// useEmptyPassphrase: !item.passphrase,
showOnOneKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import dnxGetTrackingKey from './method/dnxGetTrackingKey';
import tonGetAddress from './method/tonGetAddress';
import scdoGetAddress from './method/scdoGetAddress';
import alephiumGetAddress from './method/alephiumGetAddress';
import polkadotGetAddress from './method/polkadotGetAddress';
import algoGetAddress from './method/algoGetAddress';
import nervosGetAddress from './method/nervosGetAddress';
import nexaGetAddress from './method/nexaGetAddress';
import xrpGetAddress from './method/xrpGetAddress';
import cosmosGetAddress from './method/cosmosGetAddress';

export default {
btcGetAddress,
Expand All @@ -16,4 +22,10 @@ export default {
tonGetAddress,
scdoGetAddress,
alephiumGetAddress,
polkadotGetAddress,
algoGetAddress,
nervosGetAddress,
nexaGetAddress,
xrpGetAddress,
cosmosGetAddress,
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function alephiumGetAddress(
const [pathPrefix, lastIndex] = getPathParts(path);
let pathIndex = lastIndex;

// eslint-disable-next-line no-constant-condition
while (true) {
const relativePath = `${pathPrefix}/${pathIndex}`;
const { address, success, error } = deriveAddress(seed, relativePath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { Success, Unsuccessful } from '@onekeyfe/hd-core';
import { sha512_256 as sha512 } from '@noble/hashes/sha512';
import { base32 } from '@scure/base';
import { deriveKeyPairWithPath, mnemonicToSeed } from '../helper';

const ALGORAND_ADDRESS_BYTE_LENGTH = 36;
const ALGORAND_CHECKSUM_BYTE_LENGTH = 4;
const ALGORAND_ADDRESS_LENGTH = 58;
const ALGORAND_PUBLIC_KEY_LENGTH = 32;

function publicKeyToAddress(publicKey: Uint8Array): string {
const checksum = sha512(publicKey).slice(
ALGORAND_PUBLIC_KEY_LENGTH - ALGORAND_CHECKSUM_BYTE_LENGTH,
ALGORAND_PUBLIC_KEY_LENGTH
);
console.log('checksum', checksum);

// publicKey + checksum
const concat = new Uint8Array([...publicKey, ...checksum]);
const addr = base32.encode(concat);
console.log('addr', addr);
return addr.toString().slice(0, ALGORAND_ADDRESS_LENGTH);
}

export default function algoGetAddress(
connectId: string,
deviceId: string,
params: any & {
mnemonic: string;
passphrase?: string;
}
):
| Unsuccessful
| Success<{
address: string;
path: string;
}> {
const { path, mnemonic, passphrase } = params;

const seed = mnemonicToSeed(mnemonic, passphrase);
const keyPair = deriveKeyPairWithPath(seed, path, 'ed25519');

const { privateKey: privateKeyArray, publicKey: publicKeyArray } = keyPair;

if (!privateKeyArray || !publicKeyArray) {
return {
success: false,
payload: {
error: 'privateKey or publicKey is undefined',
},
};
}

const publicKey = publicKeyArray.slice(1);
const address = publicKeyToAddress(publicKey);

return {
success: true,
payload: {
address,
path,
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,58 @@ function getAddressTypeByPath(path: string) {
}
}

const NetworkMap = {
btc: bitcoin.networks.bitcoin,
testnet: bitcoin.networks.testnet,
doge: {
messagePrefix: '\x19Dogecoin Signed Message:\n',
bech32: '',
bip32: {
public: 0x02_fa_ca_fd,
private: 0x02_fa_c3_98,
},
pubKeyHash: 0x1e,
scriptHash: 0x16,
wif: 0x9e,
maximumFeeRate: 1_000_000, // doge
},
ltc: {
messagePrefix: '\x19Litecoin Signed Message:\n',
bech32: 'ltc',
// TODO getVersionBytesByAddressEncoding
// EAddressEncodings.P2PKH read .bip32, others read .segwitVersionBytes
bip32: {
public: 0x01_9d_a4_62,
private: 0x01_9d_9c_fe,
},
pubKeyHash: 0x30,
scriptHash: 0x32,
wif: 0xb0,
},
neurai: {
messagePrefix: '\x19Neuraium Signed Message:\n',
bech32: '',
bip32: {
public: 0x04_88_ad_e4,
private: 0x04_88_b2_1e,
},
pubKeyHash: 0x35,
scriptHash: 0x75,
wif: 0x80,
},
dash: {
messagePrefix: '\x19DarkCoin Signed Message:\n',
bech32: '',
bip32: {
public: 0x02_fe_52_cc,
private: 0x02_fe_52_f8,
},
pubKeyHash: 0x4c,
scriptHash: 0x10,
wif: 0xcc,
},
};

function getBtcAddress(type: string, publicKey: Buffer, network: bitcoin.networks.Network) {
let data;
// p2pkh
Expand Down Expand Up @@ -77,7 +129,7 @@ export default function btcGetAddress(
}> {
const { path, coin, mnemonic, passphrase } = params;

const network = bitcoin.networks.bitcoin;
const network = NetworkMap[coin as keyof typeof NetworkMap];
const seed = mnemonicToSeed(mnemonic, passphrase);

const keyPair = deriveKeyPairWithPath(seed, path);
Expand Down
Loading

0 comments on commit 90781b7

Please sign in to comment.