Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ describe("avalanche-sign-request", () => {
"00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000007000000000089544000000000000000000000000100000001512e7191685398f00663e12197a3d8f6012d9ea300000001db720ad6707915cc4751fb7e5491a3af74e127a1d81817abe9438590c0833fe10000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000050000000000989680000000010000000000000000",
"hex"
);
const mfp = "1250B6BC";
const xpub =
"xpub661MyMwAqRbcFFDMuFiGQmA1EqWxxgDLdtNvxxiucf9qkfoVrvwgnYyshxWoewWtkZ1aLhKoVDrpeDvn1YRqxX2szhGKi3UiSEv1hYRMF8q";
const walletIndex = 0;
const derivationPath = "m/44'/133'/0'/0/0";
const utxos = [];


const avalancheSignRequest = AvalancheSignRequest.constructAvalancheRequest(
avalancheData,
mfp,
xpub,
walletIndex
derivationPath,
utxos
);

const request = AvalancheSignRequest.fromDataItem(
Expand Down
2 changes: 1 addition & 1 deletion packages/ur-registry-avalanche/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@keystonehq/bc-ur-registry-avalanche",
"version": "0.0.5",
"version": "0.0.6",
"description": "bc-ur-registry extension for Avalanche",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
Expand Down
66 changes: 34 additions & 32 deletions packages/ur-registry-avalanche/src/AvalancheSignRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,48 @@ import {
RegistryItem,
extend,
DataItemMap,
CryptoKeypath,
} from "@keystonehq/bc-ur-registry";
import { ExtendedRegistryTypes } from "./RegistryType";
import * as uuid from "uuid";
import { AvalancheUtxo, AvalancheUtxoData } from "./AvalancheUtxo";

const { RegistryTypes } = extend;

type signRequestProps = {
requestId?: Buffer;
data: Buffer;
mfp: Buffer;
xpub: string;
walletIndex: number;
derivationPath: CryptoKeypath;
utxos: AvalancheUtxo[];
};

enum Keys {
requestId = 1,
signData = 2,
mfp = 3,
xpub = 6,
walletIndex = 7,
signData,
derivationPath,
utxos,
}

export class AvalancheSignRequest extends RegistryItem {
private requestId?: Buffer;
private data: Buffer;
private mfp: Buffer;
private xpub: string;
private walletIndex: number;
private derivationPath: CryptoKeypath;
private utxos: AvalancheUtxo[];


getRegistryType = () => ExtendedRegistryTypes.AVALANCHE_SIGN_REQUEST;

constructor(args: signRequestProps) {
super();
this.requestId = args.requestId;
this.data = args.data;
this.mfp = args.mfp;
this.xpub = args.xpub;
this.walletIndex = args.walletIndex;
this.derivationPath = args.derivationPath;
this.utxos = args.utxos;
}

public getRequestId = () => this.requestId;
public getSignData = () => this.data;
public getUtxos = () => this.utxos;
public getDerivationPath = () => this.derivationPath;

public toDataItem = () => {
const map: DataItemMap = {};
Expand All @@ -56,40 +56,40 @@ export class AvalancheSignRequest extends RegistryItem {
}

map[Keys.signData] = Buffer.from(this.data);
map[Keys.mfp] = this.mfp.readUInt32BE(0);
map[Keys.xpub] = this.xpub;
map[Keys.walletIndex] = Number(this.walletIndex);
map[Keys.derivationPath] = this.derivationPath;
map[Keys.utxos] = this.utxos.map((utxo) => {
const res = utxo.toDataItem();
res.setTag(utxo.getRegistryType().getTag());
return res;
});

return new DataItem(map);
};

public static fromDataItem = (dataItem: DataItem) => {
const map = dataItem.getData();
const masterFingerprint = Buffer.alloc(4);
const _masterFingerprint = map[Keys.mfp];
masterFingerprint.writeUInt32BE(_masterFingerprint, 0);
const requestId = map[Keys.requestId]
? map[Keys.requestId].getData()
: undefined;
const data = map[Keys.signData];
const xpub = map[Keys.xpub];
const walletIndex = map[Keys.signData];
const derivationPath = map[Keys.signData];
const utxos: AvalancheUtxo[] = map[Keys.utxos].map((utxo: DataItem) =>
AvalancheUtxo.fromDataItem(utxo)
);

return new AvalancheSignRequest({
requestId,
data,
xpub,
walletIndex,
mfp: masterFingerprint,
derivationPath,
utxos,
});
};

public static constructAvalancheRequest(
data: Buffer,
mfp: string,
xpub: string,
walletIndex: number,
requestId?: string | Buffer
derivationPath: CryptoKeypath,
utxos: AvalancheUtxoData[],
requestId?: string | Buffer,
) {
let _requestId;
if (typeof requestId === "string") {
Expand All @@ -99,13 +99,15 @@ export class AvalancheSignRequest extends RegistryItem {
} else {
_requestId = Buffer.from(uuid.parse(uuid.v4()) as Uint8Array);
}
const avalancheUtxos = utxos.map((utxo) =>
AvalancheUtxo.constructAvalancheUtxo(utxo)
);

return new AvalancheSignRequest({
data,
requestId: _requestId,
mfp: Buffer.from(mfp, "hex"),
xpub,
walletIndex,
derivationPath,
utxos: avalancheUtxos,
});
}
}
100 changes: 100 additions & 0 deletions packages/ur-registry-avalanche/src/AvalancheUtxo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {
CryptoKeypath,
extend,
DataItem,
PathComponent,
RegistryItem,
DataItemMap,
} from "@keystonehq/bc-ur-registry";
import { ExtendedRegistryTypes } from "./RegistryType";

const { decodeToDataItem } = extend;

enum Keys {
txid = 1,
vout,
path,
}

export interface AvalancheUtxoProps {
txid: Buffer;
vout: number;
path: CryptoKeypath;
}

export interface AvalancheUtxoData {
txid: string;
vout: number;
path: string;
}

export class AvalancheUtxo extends RegistryItem {
private txid: Buffer;
private vout: number;
private path: CryptoKeypath;

getRegistryType = () => ExtendedRegistryTypes.AVALANCHE_UTXO;

constructor(args: AvalancheUtxoProps) {
super();
this.txid = args.txid;
this.vout = args.vout;
this.path = args.path;
}

public getTxid = () => this.txid;
public getVout = () => this.vout;
public getKeyPath = () => this.path.getPath();

public toDataItem = () => {
const map: DataItemMap = {};
map[Keys.txid] = this.txid;
map[Keys.vout] = this.vout;

const keyPath = this.path.toDataItem();
keyPath.setTag(this.path.getRegistryType().getTag());
map[Keys.path] = keyPath;

return new DataItem(map);
};

public static fromDataItem = (dataItem: DataItem) => {
const map = dataItem.getData();
const txid = map[Keys.txid];
const vout = map[Keys.vout];
const path = CryptoKeypath.fromDataItem(map[Keys.path]);

return new AvalancheUtxo({
txid,
vout,
path,
});
};

public static fromCBOR = (_cborPayload: Buffer) => {
const dataItem = decodeToDataItem(_cborPayload);
return AvalancheUtxo.fromDataItem(dataItem);
};

public static constructAvalancheUtxo({
txid,
vout,
path,
}: AvalancheUtxoData) {
const paths = path.replace(/[m|M]\//, "").split("/");
const hdPathObject = new CryptoKeypath(
paths.map((path) => {
const index = parseInt(path.replace("'", ""));
const isHardened = path.endsWith("'");
return new PathComponent({ index, hardened: isHardened });
}),
);

return new AvalancheUtxo({
txid: Buffer.from(txid, "hex"),
vout,
path: hdPathObject,
});
}
}

1 change: 1 addition & 0 deletions packages/ur-registry-avalanche/src/RegistryType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { RegistryType } from "@keystonehq/bc-ur-registry";
export const ExtendedRegistryTypes = {
AVALANCHE_SIGN_REQUEST: new RegistryType("avax-sign-request", 8301),
AVALANCHE_SIGNATURE: new RegistryType("avax-signature", 8302),
AVALANCHE_UTXO: new RegistryType("avax-utxo", 8303),
};