-
Notifications
You must be signed in to change notification settings - Fork 513
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
[Feature] Generate Wallet from secret numbers #1799
Changes from all commits
42bb7bb
99fb3bd
976a77a
55245e0
75ccbbd
02f638f
8e14f6a
01a3938
ce833a6
ea32c88
e558399
88e9b4d
63c469f
c655993
45b8d91
22e104e
700a18b
7efdbe7
15cfee9
7e83e17
e50e7a2
d606d9c
130594d
451cdbf
a8d3a93
0336c26
ca9cebf
d3a467a
d416f5a
91f9f9a
74bf3b7
db77d01
61d62fd
ac17c09
0eef2c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Account } from 'xrpl-secret-numbers' | ||
|
||
import ECDSA from '../ECDSA' | ||
|
||
import { Wallet } from '.' | ||
|
||
/** | ||
* Derives a wallet from secret numbers. | ||
* NOTE: This uses a default encoding algorithm of secp256k1 to match the popular wallet | ||
* [Xumm (aka Xaman)](https://xumm.app/)'s behavior. | ||
* This may be different from the DEFAULT_ALGORITHM for other ways to generate a Wallet. | ||
* | ||
* @param secretNumbers - A string consisting of 8 times 6 numbers (whitespace delimited) used to derive a wallet. | ||
* @param opts - (Optional) Options to derive a Wallet. | ||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account. | ||
* @param opts.algorithm - The digital signature algorithm to generate an address for. | ||
* @returns A Wallet derived from secret numbers. | ||
* @throws ValidationError if unable to derive private key from secret number input. | ||
*/ | ||
export function walletFromSecretNumbers( | ||
secretNumbers: string[] | string, | ||
opts?: { masterAddress?: string; algorithm?: ECDSA }, | ||
): Wallet { | ||
const secret = new Account(secretNumbers).getFamilySeed() | ||
const updatedOpts: { masterAddress?: string; algorithm?: ECDSA } = { | ||
masterAddress: undefined, | ||
algorithm: undefined, | ||
} | ||
// Use secp256k1 since that's the algorithm used by popular wallets like Xumm when generating secret number accounts | ||
if (opts === undefined) { | ||
updatedOpts.algorithm = ECDSA.secp256k1 | ||
} else { | ||
updatedOpts.masterAddress = opts.masterAddress | ||
updatedOpts.algorithm = opts.algorithm ?? ECDSA.secp256k1 | ||
} | ||
return Wallet.fromSecret(secret, updatedOpts) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,12 @@ | ||
import { assert } from 'chai' | ||
import { decode } from 'ripple-binary-codec' | ||
|
||
import { NFTokenMint, Payment, Transaction } from '../../src' | ||
import { | ||
NFTokenMint, | ||
Payment, | ||
Transaction, | ||
walletFromSecretNumbers, | ||
} from '../../src' | ||
import ECDSA from '../../src/ECDSA' | ||
import { Wallet } from '../../src/Wallet' | ||
import requests from '../fixtures/requests' | ||
|
@@ -297,6 +302,86 @@ describe('Wallet', function () { | |
}) | ||
}) | ||
|
||
describe('fromSecretNumbers', function () { | ||
const secretNumbersString = | ||
'399150 474506 009147 088773 432160 282843 253738 605430' | ||
const secretNumbersArray = [ | ||
'399150', | ||
'474506', | ||
'009147', | ||
'088773', | ||
'432160', | ||
'282843', | ||
'253738', | ||
'605430', | ||
] | ||
|
||
const publicKey = | ||
'03BFC2F7AE242C3493187FA0B72BE97B2DF71194FB772E507FF9DEA0AD13CA1625' | ||
const privateKey = | ||
'00B6FE8507D977E46E988A8A94DB3B8B35E404B60F8B11AC5213FA8B5ABC8A8D19' | ||
// TODO: Uncomment when the `deriveKeypair` fix is merged so `deriveSecretNumbers` with ed25519 works. | ||
// const publicKeyED25519 = | ||
// 'ED8079E575450E256C496578480020A33E19B579D58A2DB8FF13FC6B05B9229DE3' | ||
// const privateKeyED25519 = | ||
// 'EDD2AF6288A903DED9860FC62E778600A985BDF804E40BD8266505553E3222C3DA' | ||
|
||
it('derives a wallet using default algorithm', function () { | ||
const wallet = walletFromSecretNumbers(secretNumbersString) | ||
|
||
assert.equal(wallet.publicKey, publicKey) | ||
assert.equal(wallet.privateKey, privateKey) | ||
}) | ||
|
||
it('derives a wallet from secret numbers as an array using default algorithm', function () { | ||
const wallet = walletFromSecretNumbers(secretNumbersArray) | ||
|
||
assert.equal(wallet.publicKey, publicKey) | ||
assert.equal(wallet.privateKey, privateKey) | ||
}) | ||
|
||
it('derives a wallet using algorithm ecdsa-secp256k1', function () { | ||
const algorithm = ECDSA.secp256k1 | ||
const wallet = walletFromSecretNumbers(secretNumbersString, { | ||
algorithm, | ||
}) | ||
|
||
assert.equal(wallet.publicKey, publicKey) | ||
assert.equal(wallet.privateKey, privateKey) | ||
}) | ||
|
||
// TODO: Uncomment this test when the `deriveKeypair` fix is merged | ||
// it('derives a wallet using algorithm ed25519', function () { | ||
// const algorithm = ECDSA.ed25519 | ||
// const wallet = Wallet.fromSecretNumbers(secretNumbersString, { | ||
// algorithm, | ||
// }) | ||
|
||
// assert.equal(wallet.publicKey, publicKeyED25519) | ||
// assert.equal(wallet.privateKey, privateKeyED25519) | ||
// }) | ||
Comment on lines
+353
to
+362
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test fails because of this issue: #2376 Commented with a TODO to re-add the test once that PR is resolved. (Open to other ideas about what's the best way to handle this :) ) |
||
|
||
it('derives a wallet using a Regular Key Pair', function () { | ||
const masterAddress = 'rUAi7pipxGpYfPNg3LtPcf2ApiS8aw9A93' | ||
const regularKeyPair = { | ||
secretNumbers: | ||
'399150 474506 009147 088773 432160 282843 253738 605430', | ||
publicKey: | ||
'03BFC2F7AE242C3493187FA0B72BE97B2DF71194FB772E507FF9DEA0AD13CA1625', | ||
privateKey: | ||
'00B6FE8507D977E46E988A8A94DB3B8B35E404B60F8B11AC5213FA8B5ABC8A8D19', | ||
} | ||
|
||
const wallet = walletFromSecretNumbers(regularKeyPair.secretNumbers, { | ||
masterAddress, | ||
}) | ||
|
||
assert.equal(wallet.publicKey, regularKeyPair.publicKey) | ||
assert.equal(wallet.privateKey, regularKeyPair.privateKey) | ||
assert.equal(wallet.classicAddress, masterAddress) | ||
}) | ||
}) | ||
|
||
describe('fromEntropy', function () { | ||
let entropy: number[] | ||
const publicKey = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be included in the monorepo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe wait to bring it up to the top level until another package needs it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no i mean, should
xrpl-secret-numbers
's source be in this monorepo. not sure where else it's used or how big it is, but that might make senseThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sure the XRPL-Labs team uses this lib in their XUMM app. I think @WietseWind is the maintainer?
For now I would leave it as "external" import and would not add it to the monorepo. but maybe Wietse thinks this would be a good idea :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ledhed2222 It's a fairly small package, and the (non dev) dependencies overlap with
ripple-keypairs
(brorand, ripple-keypairs)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that would be a good reason to maintain it within the monorepo :)
IMO, the criteria for whether it should be part of the monorepo:
ripple-keypairs
simultaneously.