Skip to content

Commit

Permalink
Merge pull request #138 from Team-Kujira/feat/kujira
Browse files Browse the repository at this point in the history
Feat / Kujira
  • Loading branch information
fengtality committed Sep 6, 2023
2 parents acbadba + c62abff commit 31fe4f6
Show file tree
Hide file tree
Showing 27 changed files with 35,344 additions and 404 deletions.
7 changes: 5 additions & 2 deletions package.json
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
@@ -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
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
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

0 comments on commit 31fe4f6

Please sign in to comment.