Skip to content

Commit

Permalink
feat: added the derivative queries to be consumed in the backend
Browse files Browse the repository at this point in the history
  • Loading branch information
SissonJ committed Feb 29, 2024
1 parent 7afa150 commit f8d5988
Show file tree
Hide file tree
Showing 9 changed files with 462 additions and 17 deletions.
54 changes: 54 additions & 0 deletions docs/queries/derivativeShd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Shade Derivative Examples

This page demonstrates how to query the Shade derivative contracts


## Staking Info

**input**

```ts
/**
* query derivative contract for the staking info
*/
async function queryDerivativeShdStakingInfo({
contractAddress,
codeHash,
lcdEndpoint,
chainId,
}: {
contractAddress: string,
codeHash?: string,
lcdEndpoint?: string,
chainId?: string,
}): Promise<ParsedStakingInfoResponse>
```

**output**

```ts
type ParsedStakingInfoResponse = {
unbondingTime: string,
bondedShd: string,
availableShd: string,
rewards: string,
totalDerivativeTokenSupply: string,
price: number,
feeInfo: ParsedFeeResponse,
status: StatusLevel,
}
// type references below
type ParsedFeeResponse = {
stakingFee: number,
unbondingFee: number,
feeCollector: string,
}
enum StatusLevel {
NORMAL_RUN = 'normal_run',
PANICKED = 'panicked',
STOP_ALL = 'stop_all'
}
```
119 changes: 119 additions & 0 deletions src/contracts/definitions/derivativeShd.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import {
test,
expect,
vi,
} from 'vitest';
import {
msgQueryStakingInfo,
msgQueryFeeInfo,
msgQueryContractStatus,
msgQueryUserHoldings,
msgQueryUserUnbondings,
msgDerivativeShdStake,
msgDerivativeShdUnbond,
msgDerivativeShdTransferStaked,
} from '~/contracts/definitions/derivativeShd';
import { snip20 } from './snip20';

vi.mock('~/contracts/definitions/snip20', () => ({
snip20: {
messages: {
send: vi.fn(() => 'SEND_MSG'),
},
},
}));

vi.mock('~/lib/utils', () => ({
generatePadding: vi.fn(() => 'RANDOM_PADDING'),
}));

test('it tests the form of the query staking info msg', () => {
const output = { staking_info: {} };
expect(msgQueryStakingInfo()).toStrictEqual(output);
});

test('it tests the form of the query fee info msg', () => {
const output = { fee_info: {} };
expect(msgQueryFeeInfo()).toStrictEqual(output);
});

test('it tests the form of the query contract status msg', () => {
const output = { contract_status: {} };
expect(msgQueryContractStatus()).toStrictEqual(output);
});

test('it tests the form of the query user holdings msg', () => {
const output = {
holdings: {
address: 'USER_ADDR',
viewing_key: 'VIEWING_KEY',
},
};
expect(msgQueryUserHoldings('USER_ADDR', 'VIEWING_KEY')).toStrictEqual(output);
});

test('it tests the form of the query user unbondings msg', () => {
const output = {
unbondings: {
address: 'USER_ADDR',
viewing_key: 'VIEWING_KEY',
},
};
expect(msgQueryUserUnbondings('USER_ADDR', 'VIEWING_KEY')).toStrictEqual(output);
});

test('it tests the form of the stake execute msg', () => {
const stakeInput = {
derivativeShdContractAddress: 'SHD_DERIVATIVE_CONTRACT_ADDRESS',
derivativeShdCodeHash: 'SHD_DERIVATIVE_CODE_HASH',
sendAmount: 'SEND_AMOUNT',
minExpectedReturnAmount: 'MINIMUM_RETURN',
};
msgDerivativeShdStake(stakeInput);
expect(snip20.messages.send).toHaveBeenCalledWith({
recipient: stakeInput.derivativeShdContractAddress,
recipientCodeHash: stakeInput.derivativeShdCodeHash,
amount: stakeInput.sendAmount,
handleMsg: {
stake: {},
},
padding: 'RANDOM_PADDING',
});
});

test('it tests the form of the unbond execute msg', () => {
const stakeInput = {
derivativeShdContractAddress: 'SHD_DERIVATIVE_CONTRACT_ADDRESS',
derivativeShdCodeHash: 'SHD_DERIVATIVE_CODE_HASH',
sendAmount: 'SEND_AMOUNT',
};
msgDerivativeShdUnbond(stakeInput);
expect(snip20.messages.send).toHaveBeenCalledWith({
recipient: stakeInput.derivativeShdContractAddress,
recipientCodeHash: stakeInput.derivativeShdCodeHash,
amount: stakeInput.sendAmount,
handleMsg: {
unbond: {},
},
padding: 'RANDOM_PADDING',
});
});

test('it tests the form of the unbond execute msg', () => {
const stakeInput = {
derivativeShdContractAddress: 'SHD_DERIVATIVE_CONTRACT_ADDRESS',
derivativeShdCodeHash: 'SHD_DERIVATIVE_CODE_HASH',
sendAmount: 'SEND_AMOUNT',
receiver: 'RECEIVER_ADDRESS',
};
msgDerivativeShdTransferStaked(stakeInput);
expect(snip20.messages.send).toHaveBeenCalledWith({
recipient: stakeInput.derivativeShdContractAddress,
recipientCodeHash: stakeInput.derivativeShdCodeHash,
amount: stakeInput.sendAmount,
handleMsg: {
unbond: {},
},
padding: 'RANDOM_PADDING',
});
});
50 changes: 48 additions & 2 deletions src/contracts/definitions/derivativeShd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,57 @@ function msgDerivativeShdStake({
derivativeShdContractAddress: string,
derivativeShdCodeHash?: string,
sendAmount: string,
minExpectedReturnAmount: string, // param doesn't exist in the contract yet
minExpectedReturnAmount?: string, // param doesn't exist in the contract yet
}) {
return snip20.messages.send({
recipient: derivativeShdContractAddress,
recipientCodeHash: derivativeShdCodeHash,
amount: sendAmount,
handleMsg: {}, // TBD for minExpectedReturn
handleMsg: { stake: {} }, // TBD for minExpectedReturn
padding: generatePadding(),
}).msg;
}

/**
* message to stake shd to receive derivative shade
*/
function msgDerivativeShdUnbond({
derivativeShdContractAddress,
derivativeShdCodeHash,
sendAmount,
}: {
derivativeShdContractAddress: string,
derivativeShdCodeHash?: string,
sendAmount: string,
}) {
return snip20.messages.send({
recipient: derivativeShdContractAddress,
recipientCodeHash: derivativeShdCodeHash,
amount: sendAmount,
handleMsg: { unbond: {} },
padding: generatePadding(),
}).msg;
}

/**
* message to stake shd to receive derivative shade
*/
function msgDerivativeShdTransferStaked({
derivativeShdContractAddress,
derivativeShdCodeHash,
sendAmount,
receiver,
}: {
derivativeShdContractAddress: string,
derivativeShdCodeHash?: string,
sendAmount: string,
receiver: string,
}) {
return snip20.messages.send({
recipient: derivativeShdContractAddress,
recipientCodeHash: derivativeShdCodeHash,
amount: sendAmount,
handleMsg: { transfer_staked: { receiver } },
padding: generatePadding(),
}).msg;
}
Expand All @@ -66,4 +110,6 @@ export {
msgQueryUserHoldings,
msgQueryUserUnbondings,
msgDerivativeShdStake,
msgDerivativeShdUnbond,
msgDerivativeShdTransferStaked,
};
74 changes: 74 additions & 0 deletions src/contracts/services/derivativeShd.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
test,
expect,
vi,
beforeAll,
} from 'vitest';
import { of } from 'rxjs';
import stakingInfoResponse from '~/test/mocks/derivativeShd/stakingInfoResponse.json';
import { stakingInfoResponseParsed } from '~/test/mocks/derivativeShd/stakingInfoResponseParsed';
import { StakingInfoResponse } from '~/types/contracts/derivativeShd/response';
import { parseDerivativeShdStakingInfo, queryDerivativeShdStakingInfo, queryDerivativeShdStakingInfo$ } from '~/contracts/services/derivativeShd';

const sendSecretClientContractQuery$ = vi.hoisted(() => vi.fn());

beforeAll(() => {
vi.mock('~/contracts/definitions/derivativeShd', () => ({
msgQueryStakingInfo: vi.fn(() => 'STAKING_INFO_MSG'),
}));

vi.mock('~/client/index', () => ({
getActiveQueryClient$: vi.fn(() => of({ client: 'CLIENT' })),
}));

vi.mock('~/client/services/clientServices', () => ({
sendSecretClientContractQuery$,
}));
});

test('it can parse the staking info', () => {
expect(parseDerivativeShdStakingInfo(
stakingInfoResponse as StakingInfoResponse,
)).toStrictEqual(stakingInfoResponseParsed);
});

test('it can call the query staking info service', async () => {
// observables function
sendSecretClientContractQuery$.mockReturnValueOnce(of(stakingInfoResponse));

const input = {
contractAddress: 'CONTRACT_ADDRESS',
codeHash: 'CODE_HASH',
lcdEndpoint: 'LCD_ENDPOINT',
chainId: 'CHAIN_ID',
};

let output;
queryDerivativeShdStakingInfo$(input).subscribe({
next: (response) => {
output = response;
},
});

expect(sendSecretClientContractQuery$).toHaveBeenCalledWith({
queryMsg: 'STAKING_INFO_MSG',
client: 'CLIENT',
contractAddress: input.contractAddress,
codeHash: input.codeHash,
});

expect(output).toStrictEqual(stakingInfoResponseParsed);

// async/await function
sendSecretClientContractQuery$.mockReturnValueOnce(of(stakingInfoResponse));
const output2 = await queryDerivativeShdStakingInfo(input);

expect(sendSecretClientContractQuery$).toHaveBeenCalledWith({
queryMsg: 'STAKING_INFO_MSG',
client: 'CLIENT',
contractAddress: input.contractAddress,
codeHash: input.codeHash,
});

expect(output2).toStrictEqual(stakingInfoResponseParsed);
});
Loading

0 comments on commit f8d5988

Please sign in to comment.