Skip to content
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

DRAFT: Add Kujira #3

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions examples/sandbox/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,18 @@ <h4>Osmosis</h4>
<input type="text" id="osmosisResults" />
</div>

<div class="container">
<h4>Kujira</h4>
<button class="button button-outline" id="kujiraAddress">Get Address</button>
<button class="button button-outline" id="kujiraSend">Send</button>
<button class="button button-outline" id="kujiraDelegate">Delegate</button>
<button class="button button-outline" id="kujiraUndelegate">Undelegate</button>
<button class="button button-outline" id="kujiraRedelegate">Redelegate</button>
<button class="button button-outline" id="kujiraRewards">Rewards</button>
<button class="button button-outline" id="kujiraIBCTransfer">IBC Transfer</button>
<input type="text" id="kujiraResults" />
</div>

<div class="container">
<h4>Arkeo</h4>
<button class="button button-outline" id="arkeoGetAddress">Get Address</button>
Expand Down
182 changes: 182 additions & 0 deletions examples/sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ import {
osmosisSwapTx,
osmosisUndelegateTx,
} from "./json/osmosis/osmosisAminoTx.json";
import {
kujiraDelegateTx,
kujiraIBCTransferTx,
kujiraRedelegateTx,
kujiraRewardsTx,
kujiraSendTx,
kujiraUndelegateTx,
} from "./json/kujira/kujiraAminoTx.json";
import * as rippleTxJson from "./json/rippleTx.json";
import {
thorchainBinanceBaseTx,
Expand Down Expand Up @@ -1818,6 +1826,180 @@ $osmosisSwap.on("click", async (e) => {
}
});

/*
* Kujira
*/
const $kujiraAddress = $("#kujiraAddress");
const $kujiraSend = $("#kujiraSend");
const $kujiraDelegate = $("#kujiraDelegate");
const $kujiraUndelegate = $("#kujiraUndelegate");
const $kujiraRedelegate = $("#kujiraRedelegate");
const $kujiraRewards = $("#kujiraRewards");
const $kujiraIBCTransfer = $("#kujiraIBCTransfer");

const $kujiraResults = $("#kujiraResults");

$kujiraAddress.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const { addressNList } = wallet.kujiraGetAccountPaths({ accountIdx: 0 })[0];
const result = await wallet.kujiraGetAddress({
addressNList,
showDisplay: false,
});
await wallet.kujiraGetAddress({
addressNList,
showDisplay: true,
});
$kujiraResults.val(result);
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Lujira");
}
});

$kujiraSend.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const unsigned: core.Kujira.StdTx = kujiraSendTx;

const res = await wallet.kujiraSignTx({
addressNList: core.bip32ToAddressNList(`m/44'/118'/0'/0/0`),
chain_id: unsigned.chain_id,
account_number: unsigned.account_number,
sequence: unsigned.sequence,
tx: unsigned,
});
$kujiraResults.val(JSON.stringify(res));
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Kujira");
}
});

$kujiraDelegate.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const unsigned: core.Kujira.StdTx = kujiraDelegateTx;

const res = await wallet.kujiraSignTx({
addressNList: core.bip32ToAddressNList(`m/44'/118'/0'/0/0`),
chain_id: unsigned.chain_id,
account_number: unsigned.account_number,
sequence: unsigned.sequence,
tx: unsigned,
});
$kujiraResults.val(JSON.stringify(res));
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Kujira");
}
});

$kujiraUndelegate.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const unsigned: core.Kujira.StdTx = kujiraUndelegateTx;

const res = await wallet.kujiraSignTx({
addressNList: core.bip32ToAddressNList(`m/44'/118'/0'/0/0`),
chain_id: unsigned.chain_id,
account_number: unsigned.account_number,
sequence: unsigned.sequence,
tx: unsigned,
});
$kujiraResults.val(JSON.stringify(res));
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Kujira");
}
});

$kujiraRedelegate.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const unsigned: core.Kujira.StdTx = kujiraRedelegateTx;

const res = await wallet.kujiraSignTx({
addressNList: core.bip32ToAddressNList(`m/44'/118'/0'/0/0`),
chain_id: unsigned.chain_id,
account_number: unsigned.account_number,
sequence: unsigned.sequence,
tx: unsigned,
});
$kujiraResults.val(JSON.stringify(res));
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Kujira");
}
});

$kujiraRewards.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const unsigned: core.Kujira.StdTx = kujiraRewardsTx;

const res = await wallet.kujiraSignTx({
addressNList: core.bip32ToAddressNList(`m/44'/118'/0'/0/0`),
chain_id: unsigned.chain_id,
account_number: unsigned.account_number,
sequence: unsigned.sequence,
tx: unsigned,
});
$kujiraResults.val(JSON.stringify(res));
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Kujira");
}
});

$kujiraIBCTransfer.on("click", async (e) => {
e.preventDefault();
if (!wallet) {
$kujiraResults.val("No wallet?");
return;
}
if (core.supportsKujira(wallet)) {
const unsigned: core.Kujira.StdTx = kujiraIBCTransferTx;

const res = await wallet.kujiraSignTx({
addressNList: core.bip32ToAddressNList(`m/44'/118'/0'/0/0`),
chain_id: unsigned.chain_id,
account_number: unsigned.account_number,
sequence: unsigned.sequence,
tx: unsigned,
});
$kujiraResults.val(JSON.stringify(res));
} else {
const label = await wallet.getLabel();
$kujiraResults.val(label + " does not support Kujira");
}
});

/*
* Arkeo
*/
Expand Down
1 change: 1 addition & 0 deletions examples/sandbox/json/kujira/kujiraAnomiTx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//todo
7 changes: 7 additions & 0 deletions integration/src/kujira/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as core from "@keepkey/hdwallet-core";

import { kujiraTests as tests } from "./kujira";

export function kujiraTests(get: () => { wallet: core.HDWallet; info: core.HDWalletInfo }): void {
tests(get);
}
3 changes: 2 additions & 1 deletion packages/hdwallet-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export * from "./exceptions";
export * from "./fio";
export * from "./kava";
export * from "./keyring";
export * from "./kujira";
export * from "./mayachain";
export * from "./ripple";
export * from "./secret";
export * from "./terra";
export * from "./thorchain";
export * from "./mayachain";
export * from "./transport";
export * from "./utils";
export * from "./wallet";
139 changes: 139 additions & 0 deletions packages/hdwallet-core/src/kujira.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { addressNListToBIP32, slip44ByCoin } from "./utils";
import { BIP32Path, HDWallet, HDWalletInfo, PathDescription } from "./wallet";

export interface KujiraGetAddress {
addressNList: BIP32Path;
showDisplay?: boolean;
}

// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace Kujira {
export interface Msg {
type: string;
value: any;
}

export type Coins = Coin[];

export interface Coin {
denom: string;
amount: string;
}

export interface StdFee {
amount: Coins;
gas: string;
}

// eslint-disable-next-line @typescript-eslint/no-namespace
namespace crypto {
export interface PubKey {
type: string;
value: string;
}
}

export interface StdSignature {
pub_key?: crypto.PubKey;
signature: string;
}

export interface StdTx {
msg: Msg[];
fee: StdFee;
signatures: StdSignature[];
memo?: string;
}
}

export interface KujiraTx {
msg: Kujira.Msg[];
fee: Kujira.StdFee;
signatures: Kujira.StdSignature[];
memo?: string;
}

export interface KujiraSignTx {
addressNList: BIP32Path;
tx: Kujira.StdTx;
chain_id: string;
account_number: string;
sequence: string;
fee?: number;
}

export interface KujiraSignedTx {
serialized: string;
body: string;
authInfoBytes: string;
signatures: string[];
}

export interface KujiraGetAccountPaths {
accountIdx: number;
}

export interface KujiraAccountPath {
addressNList: BIP32Path;
}

export interface KujiraWalletInfo extends HDWalletInfo {
readonly _supportsKujiraInfo: boolean;

/**
* Returns a list of bip32 paths for a given account index in preferred order
* from most to least preferred.
*/
KujiraGetAccountPaths(msg: KujiraGetAccountPaths): Array<KujiraAccountPath>;

/**
* Returns the "next" account path, if any.
*/
kujiraNextAccountPath(msg: KujiraAccountPath): KujiraAccountPath | undefined;
}

export interface KujiraWallet extends KujiraWalletInfo, HDWallet {
readonly _supportsKujira: boolean;

kujiraGetAddress(msg: KujiraGetAddress): Promise<string | null>;
kujiraSignTx(msg: KujiraSignTx): Promise<KujiraSignedTx | null>;
}

export function kujiraDescribePath(path: BIP32Path): PathDescription {
const pathStr = addressNListToBIP32(path);
const unknown: PathDescription = {
verbose: pathStr,
coin: "Kuji",
isKnown: false,
};

if (path.length != 5) {
return unknown;
}

if (path[0] != 0x80000000 + 44) {
return unknown;
}

if (path[1] != 0x80000000 + slip44ByCoin("Kuji")) {
return unknown;
}

if ((path[2] & 0x80000000) >>> 0 !== 0x80000000) {
return unknown;
}

if (path[3] !== 0 || path[4] !== 0) {
return unknown;
}

const index = path[2] & 0x7fffffff;
return {
verbose: `Kujira Account #${index}`,
accountIdx: index,
wholeAccount: true,
coin: "Kuji",
isKnown: true,
isPrefork: false,
};
}
1 change: 1 addition & 0 deletions packages/hdwallet-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ const slip44Table = Object.freeze({
ArbitrumNova: 60,
Mayachain: 931,
Cacao: 931,
Kujira: 118,
} as const);
type Slip44ByCoin<T> = T extends keyof typeof slip44Table ? typeof slip44Table[T] : number | undefined;
export function slip44ByCoin<T extends Coin>(coin: T): Slip44ByCoin<T> {
Expand Down
Loading