@@ -6,8 +6,9 @@ import * as noun from '../nockjs/noun';
6import * as serial from '../nockjs/serial';
6import * as serial from '../nockjs/serial';
7import * as kg from 'urbit-key-generation/dist';
7import * as kg from 'urbit-key-generation/dist';
9−import { BRIDGE_ERROR } from './error';
10−import { WALLET_TYPES, eqAddr } from './wallet';
9+import { eqAddr, addHexPrefix } from './wallet';
11+const NETWORK_KEY_CURVE_PARAMETER = '42';
12// ctsy joemfb
13// ctsy joemfb
13const b64 = buf => {
14const b64 = buf => {
@@ -50,9 +51,20 @@ const jam = seed => {
50 return Buffer.from(pad, 'hex').reverse();
51 return Buffer.from(pad, 'hex').reverse();
53−const genKey = (networkSeed, point, revision) => {
54+// simple alias to avoid importing kg into component scope
54− const pair = kg.deriveNetworkKeys(networkSeed);
55+export const deriveNetworkKeys = seed => kg.deriveNetworkKeys(seed);
58+ * @param {object} pair
59+ * @param {number} point
60+ * @param {number} revision
63+export const compileNetworkingKey = (pair, point, revision) => {
64+ const bnsec = new BN(
55− const bnsec = new BN(pair.crypt.private + pair.auth.private + '42', 'hex'); // '42' is curve parameter
65+ pair.crypt.private + pair.auth.private + NETWORK_KEY_CURVE_PARAMETER,
57 const sed = noun.dwim(
69 const sed = noun.dwim(
58 noun.Atom.fromInt(point),
70 noun.Atom.fromInt(point),
@@ -64,68 +76,93 @@ const genKey = (networkSeed, point, revision) => {
64 return b64(jam(sed));
76 return b64(jam(sed));
67−// 'next' refers to setting the next set of keys
79+/**
68−// if false, we use revision - 1
80+ * @param {Maybe<any>} urbitWallet
69−const attemptNetworkSeedDerivation = async (next, args) => {
81+ * @param {number} revision
82+ * @return {Promise<Maybe<string>>}
84+export const deriveNetworkSeedFromUrbitWallet = async (
70− const { walletType, urbitWallet, authMnemonic } = args;
85+ urbitWallet,
74− // following code is intentionally verbose for sake of clarity
76− const point = need.point(args.pointCursor);
77− const pointDetails = need.fromPointCache(args.pointCache, point);
79− const revision =
86+ revision = 1
80− next === true
87+) => {
81− ? parseInt(pointDetails.keyRevisionNumber)
88+ const _urbitWallet = need.wallet(urbitWallet);
82− : parseInt(pointDetails.keyRevisionNumber) - 1;
89+ return deriveNetworkSeedFromSeed(_urbitWallet.management.seed, revision);
84− let managementSeed = '';
86− const ticketLike = [WALLET_TYPES.TICKET, WALLET_TYPES.SHARDS];
88− if (ticketLike.includes(walletType)) {
89− const uwal = urbitWallet.matchWith({
90− Just: uw => uw.value,
92− throw BRIDGE_ERROR.MISSING_URBIT_WALLET;
96− managementSeed = uwal.management.seed;
97− } else if (walletType === WALLET_TYPES.MNEMONIC) {
98− const walProxy = need.addressFromWallet(args.wallet);
100− const mnemonic = authMnemonic.matchWith({
92+/**
101− Just: mnem => mnem.value,
93+ * @param {Maybe<any>} wallet
102− Nothing: _ => {
94+ * @param {Maybe<string>} authMnemonic
103− throw BRIDGE_ERROR.MISSING_MNEMONIC;
95+ * @param {object} details
104− },
96+ * @param {number} revision
105− });
97+ * @return {Promise<Maybe<string>>}
99+export const deriveNetworkSeedFromMnemonic = async (
105+ const _wallet = need.wallet(wallet);
106+ const _mnemonic = need.authMnemonic(authMnemonic);
107+ const isManagementProxy = eqAddr(_wallet.address, details.managementProxy);
109+ if (isManagementProxy) {
110+ return await deriveNetworkSeedFromSeed(_mnemonic, revision);
107− const chainProxy = pointDetails.managementProxy;
113+ return Nothing();
109− // the network seed is only derivable from mnemonic if the derived
116+/**
110− // management seed equals the record we have on chain
117+ * @param {string} seed
111− const networkSeedDerivable = eqAddr(walProxy, chainProxy);
118+ * @param {number} revision
119+ * @return {Promise<Maybe<string>>}
121+const deriveNetworkSeedFromSeed = async (seed, revision) => {
122+ const networkSeed = await kg.deriveNetworkSeed(seed, '', revision);
123+ // apparently deriveNetworkSeed can return empty string
124+ // and perhaps even malformed
125+ return networkSeed === '' ? Nothing() : Just(networkSeed);
113− if (networkSeedDerivable === true) {
128+/**
114− managementSeed = mnemonic;
129+ * @return {Promise<Maybe<string>>}
131+export const attemptNetworkSeedDerivation = async ({
138+ if (Just.hasInstance(urbitWallet)) {
139+ return await deriveNetworkSeedFromUrbitWallet(urbitWallet, revision);
118− if (managementSeed !== '') {
142+ if (Just.hasInstance(wallet) && Just.hasInstance(authMnemonic)) {
119− const seed = await kg.deriveNetworkSeed(managementSeed, '', revision);
143+ return await deriveNetworkSeedFromMnemonic(
121− if (seed === '') {
145+ authMnemonic,
122− return Nothing();
146+ details,
128 return Nothing();
151 return Nothing();
131−export { genKey, attemptNetworkSeedDerivation };
154+/**
156+ * @param {object} pair
157+ * @param {object} details
160+export const keysMatchChain = (pair, details) => {
161+ const { crypt, auth } = pair;
162+ const { encryptionKey, authenticationKey } = details;
165+ encryptionKey === addHexPrefix(crypt.public) &&
166+ authenticationKey === addHexPrefix(auth.public)