@transia/secret-numbers
Version:
Generate XRPL Accounts with a number-based secret: 8 chunks of 6 digits
106 lines (89 loc) • 2.38 kB
text/typescript
import {
deriveAddress,
deriveKeypair,
generateSeed,
} from '@transia/ripple-keypairs'
import {
entropyToSecret,
parseSecretString,
randomSecret,
secretToEntropy,
} from '../utils'
/* Types ==================================================================== */
export interface Keypair {
publicKey: string
privateKey: string
}
interface AccountData {
familySeed: string
address: string
keypair: Keypair
}
/* Class ==================================================================== */
export class Account {
private readonly _secret: string[]
private readonly _account: AccountData = {
familySeed: '',
address: '',
keypair: {
publicKey: '',
privateKey: '',
},
}
constructor(secretNumbers?: string[] | string | Uint8Array) {
if (typeof secretNumbers === 'string') {
this._secret = parseSecretString(secretNumbers)
} else if (Array.isArray(secretNumbers)) {
this._secret = secretNumbers
} else if (secretNumbers instanceof Uint8Array) {
this._secret = entropyToSecret(secretNumbers)
} else {
this._secret = randomSecret()
}
validateLengths(this._secret)
this.derive()
}
getSecret(): string[] {
return this._secret
}
getSecretString(): string {
return this._secret.join(' ')
}
getAddress(): string {
return this._account.address
}
getFamilySeed(): string {
return this._account.familySeed
}
getKeypair(): Keypair {
return this._account.keypair
}
toString(): string {
return this.getSecretString()
}
private derive(): void {
try {
const entropy = secretToEntropy(this._secret)
this._account.familySeed = generateSeed({ entropy })
this._account.keypair = deriveKeypair(this._account.familySeed)
this._account.address = deriveAddress(this._account.keypair.publicKey)
} catch (error) {
let message = 'Unknown Error'
if (error instanceof Error) {
message = error.message
}
// we'll proceed, but let's report it
throw new Error(message)
}
}
}
function validateLengths(secretNumbers: string[]): void {
if (secretNumbers.length !== 8) {
throw new Error('Secret must have 8 numbers')
}
secretNumbers.forEach((num) => {
if (num.length !== 6) {
throw new Error('Each secret number must be 6 digits')
}
})
}