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

Feat / Kujira #138

Merged
merged 1 commit into from
Sep 6, 2023
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
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"test:scripts": "jest -i --verbose ./test-scripts/*.test.ts"
},
"dependencies": {
"@cosmjs/proto-signing": "^0.28.10",
"@cosmjs/stargate": "^0.28.13",
"@cosmjs/proto-signing": "^0.30.1",
"@cosmjs/stargate": "^0.30.1",
"@crocswap/sdk": "^2.4.5",
"@ethersproject/abstract-provider": "5.7.0",
"@ethersproject/address": "5.7.0",
Expand Down Expand Up @@ -77,7 +77,10 @@
"express": "^4.17.1",
"express-winston": "^4.1.0",
"fs-extra": "^10.0.0",
"http-status-codes": "2.2.0",
"immutable": "^4.2.4",
"js-yaml": "^4.1.0",
"kujira.js": "^0.8.145",
"level": "^8.0.0",
"lodash": "^4.17.21",
"lru-cache": "^7.14.1",
Expand Down
231 changes: 231 additions & 0 deletions src/chains/kujira/kujira.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
import { KujiraModel } from '../../connectors/kujira/kujira.model';
import { convertToGetTokensResponse } from '../../connectors/kujira/kujira.convertors';
import { KujiraConfig } from '../../connectors/kujira/kujira.config';
import {
Address,
GetCurrentBlockRequest,
GetCurrentBlockResponse,
Token,
} from '../../connectors/kujira/kujira.types';
import { TokenInfo } from '../ethereum/ethereum-base';
import {
BalanceRequest,
PollRequest,
TokensRequest,
TokensResponse,
} from '../../network/network.requests';
import { Chain, CustomTransaction } from '../../services/common-interfaces';
import {
AllowancesRequest,
ApproveRequest,
CancelRequest,
NonceRequest,
NonceResponse,
} from '../chain.requests';
import {
TransferRequest,
TransferResponse,
} from '../injective/injective.requests';
import { BigNumber } from 'bignumber.js';

export class Kujira {
chain: string = 'kujira';
network: string;
controller: Kujira = this;

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
private kujira: KujiraModel;
storedTokenList: any;

private static _instances: { [name: string]: Kujira };

private constructor(network: string) {
this.network = network;
}

public static getInstance(chain: string): Kujira {
if (Kujira._instances === undefined) {
Kujira._instances = {};
}

const key = `${chain}`;

if (!(key in Kujira._instances)) {
Kujira._instances[key] = new Kujira(chain);
}

return Kujira._instances[key];
}

public static getConnectedInstances(): { [key: string]: Kujira } {
return Kujira._instances;
}

async init() {
this.kujira = KujiraModel.getInstance(this.chain, this.network);
await this.kujira.init();
}

ready(): boolean {
return this.kujira ? this.kujira.isReady : false;
}

async getWalletPublicKey(
mnemonic: string,
accountNumber: number | undefined
): Promise<Address> {
return await this.kujira.getWalletPublicKey({
mnemonic: mnemonic,
accountNumber: accountNumber || KujiraConfig.config.accountNumber,
});
}

async encrypt(
mnemonic: string,
accountNumber: number,
publicKey: string
): Promise<string> {
return await this.kujira.encryptWallet({
wallet: {
mnemonic,
accountNumber,
publicKey,
},
});
}

async getTokenForSymbol(symbol: string): Promise<TokenInfo> {
return convertToGetTokensResponse(await this.kujira.getToken({ symbol }));
}

async getCurrentBlockNumber(
_options: GetCurrentBlockRequest
): Promise<GetCurrentBlockResponse> {
return await this.kujira.getCurrentBlock(_options);
}

async balances(
_chain: any,
req: BalanceRequest
): Promise<{ balances: Record<string, string> }> {
let balances;
if (req.tokenSymbols && req.tokenSymbols.length) {
balances = await this.kujira.getBalances({
ownerAddress: req.address,
tokenSymbols: req.tokenSymbols,
});
} else {
balances = await this.kujira.getAllBalances({
ownerAddress: req.address,
});
}

const output: Record<string, string> = {};

for (const balance of balances.tokens.values()) {
output[(balance.token as Token).symbol] = balance.free.toString();
}

return { balances: output };
}

async poll(_chain: Chain, req: PollRequest): Promise<any> {
const currentBlock = await this.kujira.getCurrentBlock({});

const transaction = await this.kujira.getTransaction({
hash: req.txHash,
});

// noinspection UnnecessaryLocalVariableJS
const output = {
currentBlock: currentBlock,
txHash: transaction.hash,
txStatus: transaction.code,
txBlock: transaction.blockNumber,
txData: transaction.data,
txReceipt: undefined,
};

return output;
}

async getTokens(_chain: Chain, _req: TokensRequest): Promise<TokensResponse> {
const tokens = await this.kujira.getAllTokens({});

const output: {
tokens: any[];
} = {
tokens: [],
};

for (const token of tokens.values()) {
output.tokens.push({
chainId: this.kujira.chain,
address: token.id,
name: token.name,
symbol: token.symbol,
decimals: token.decimals,
});
}

return output;
}

async nextNonce(_chain: Chain, _req: NonceRequest): Promise<NonceResponse> {
// Not applicable.

return {
nonce: undefined as unknown as number,
};
}

async nonce(_chain: Chain, _req: NonceRequest): Promise<NonceResponse> {
// Not applicable.

return {
nonce: undefined as unknown as number,
};
}

async allowances(_chain: Chain, _req: AllowancesRequest): Promise<any> {
// Not applicable.

return {
spender: undefined as unknown as string,
approvals: {} as Record<string, string>,
};
}

async approve(_chain: Chain, _req: ApproveRequest): Promise<any> {
// Not applicable.

return {
tokenAddress: undefined as unknown as string,
spender: undefined as unknown as string,
amount: undefined as unknown as string,
nonce: undefined as unknown as number,
approval: undefined as unknown as CustomTransaction,
};
}

async cancel(_chain: Chain, _req: CancelRequest): Promise<any> {
// Not applicable.

return {
txHash: undefined as unknown as string,
};
}

async transfer(
_chain: Chain,
req: TransferRequest
): Promise<TransferResponse> {
return this.kujira.transferFromTo({
from: req.from,
to: req.to,
tokenSymbol: req.token,
amount: BigNumber(req.amount),
});
}
}
6 changes: 5 additions & 1 deletion src/clob/clob.validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
validateAmount,
validateSide,
} from '../amm/amm.validators';
import { isValidKujiraPublicKey } from '../connectors/kujira/kujira.helpers';

export const invalidMarketError: string =
'The market param is not a valid market. Market should be in {base}-{quote} format.';
Expand Down Expand Up @@ -95,7 +96,10 @@ export const validateWallet: Validator = mkValidator(
'address',
invalidWalletError,
(val) => {
return typeof val === 'string' && isAddress(val.slice(0, 42));
return (
typeof val === 'string' &&
(isAddress(val.slice(0, 42)) || isValidKujiraPublicKey(val))
);
}
);

Expand Down
13 changes: 12 additions & 1 deletion src/connectors/connectors.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ConnectorsResponse } from './connectors.request';
import { DexalotCLOBConfig } from './dexalot/dexalot.clob.config';
import { TinymanConfig } from './tinyman/tinyman.config';
import { PlentyConfig } from './plenty/plenty.config';
import { KujiraConfig } from './kujira/kujira.config';

export namespace ConnectorsRoutes {
export const router = Router();
Expand Down Expand Up @@ -157,7 +158,17 @@ export namespace ConnectorsRoutes {
trading_type: PlentyConfig.config.tradingTypes,
chain_type: PlentyConfig.config.chainType,
available_networks: PlentyConfig.config.availableNetworks,
}
},
{
name: 'kujira',
trading_type: KujiraConfig.config.tradingTypes,
chain_type: KujiraConfig.config.chainType,
available_networks: KujiraConfig.config.availableNetworks,
additional_add_wallet_prompts: {
accountId:
'Enter your kujira account number (input 0 if unsure) >>> ',
},
},
],
});
})
Expand Down
Loading
Loading