Skip to content

Commit

Permalink
Merge pull request #1319 from rainlanguage/2025-02-16-optional-deposits
Browse files Browse the repository at this point in the history
Making deposit calldata generation optional
  • Loading branch information
hardyjosh authored Feb 16, 2025
2 parents 3582bb5 + 3bb9862 commit a39712a
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 107 deletions.
62 changes: 29 additions & 33 deletions crates/js_api/src/gui/order_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,17 @@ pub struct AllowancesResult(Vec<TokenAllowance>);
impl_all_wasm_traits!(AllowancesResult);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
pub struct ApprovalCalldataResult(Vec<dotrain_order::calldata::ApprovalCalldata>);
pub enum ApprovalCalldataResult {
NoDeposits,
Calldatas(Vec<dotrain_order::calldata::ApprovalCalldata>),
}
impl_all_wasm_traits!(ApprovalCalldataResult);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
pub struct DepositCalldataResult(Vec<Bytes>);
pub enum DepositCalldataResult {
NoDeposits,
Calldatas(Vec<Bytes>),
}
impl_all_wasm_traits!(DepositCalldataResult);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
Expand Down Expand Up @@ -165,17 +171,17 @@ impl DotrainOrderGui {
) -> Result<ApprovalCalldataResult, GuiError> {
let deployment = self.get_current_deployment()?;
self.check_select_tokens()?;
self.check_deposits()?;

let deposits_map = self.get_deposits_as_map().await?;
if deposits_map.is_empty() {
return Ok(ApprovalCalldataResult::NoDeposits);
}

let calldatas = self
.dotrain_order
.generate_approval_calldatas(
&deployment.key,
&owner,
&self.get_deposits_as_map().await?,
)
.generate_approval_calldatas(&deployment.key, &owner, &deposits_map)
.await?;
Ok(ApprovalCalldataResult(calldatas))
Ok(ApprovalCalldataResult::Calldatas(calldatas))
}

fn populate_vault_ids(&mut self, deployment: &GuiDeployment) -> Result<(), GuiError> {
Expand Down Expand Up @@ -206,7 +212,6 @@ impl DotrainOrderGui {
pub async fn generate_deposit_calldatas(&mut self) -> Result<DepositCalldataResult, GuiError> {
let deployment = self.get_current_deployment()?;
self.check_select_tokens()?;
self.check_deposits()?;
self.populate_vault_ids(&deployment)?;
let deployment = self.get_current_deployment()?;

Expand All @@ -228,11 +233,17 @@ impl DotrainOrderGui {
Ok(((vault_id, token.address), *amount))
})
.collect::<Result<HashMap<_, _>, GuiError>>()?;

if token_deposits.is_empty() {
return Ok(DepositCalldataResult::NoDeposits);
}

let calldatas = self
.dotrain_order
.generate_deposit_calldatas(&deployment.key, &token_deposits)
.await?;
Ok(DepositCalldataResult(calldatas))

Ok(DepositCalldataResult::Calldatas(calldatas))
}

/// Generate add order calldata
Expand Down Expand Up @@ -260,42 +271,27 @@ impl DotrainOrderGui {
) -> Result<DepositAndAddOrderCalldataResult, GuiError> {
let deployment = self.get_current_deployment()?;
self.check_select_tokens()?;
self.check_deposits()?;
self.check_field_values()?;
self.populate_vault_ids(&deployment)?;
self.update_bindings(&deployment)?;
let deployment = self.get_current_deployment()?;

let token_deposits = self
.get_vaults_and_deposits(&deployment)
.await?
.iter()
.enumerate()
.map(|(i, (order_io, amount))| {
let vault_id = order_io
.vault_id
.ok_or(GuiError::VaultIdNotFound(i.to_string()))?;
let mut calls = Vec::new();

if order_io.token.is_none() {
return Err(GuiError::SelectTokensNotSet);
}
let token = order_io.token.as_ref().unwrap();
let deposit_calldatas = self.generate_deposit_calldatas().await?;

Ok(((vault_id, token.address), *amount))
})
.collect::<Result<HashMap<_, _>, GuiError>>()?;
let deposit_calldatas = match deposit_calldatas {
DepositCalldataResult::Calldatas(calldatas) => calldatas,
DepositCalldataResult::NoDeposits => Vec::new(),
};

let mut calls = Vec::new();
let deposit_calldatas = self
.dotrain_order
.generate_deposit_calldatas(&deployment.key, &token_deposits)
.await?;
let add_order_calldata = self
.dotrain_order
.generate_add_order_calldata(&deployment.key)
.await?;

calls.push(Bytes::copy_from_slice(&add_order_calldata));

for calldata in deposit_calldatas.iter() {
calls.push(Bytes::copy_from_slice(calldata));
}
Expand Down
77 changes: 27 additions & 50 deletions packages/orderbook/test/js_api/gui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function ()
.once()
.withBodyIncluding('0x82ad56cb')
.thenSendJsonRpcResult(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
);
dotrain3 = `${guiConfig3}
Expand Down Expand Up @@ -887,16 +887,24 @@ ${dotrainWithoutVaultIds}
gui.saveDeposit('token1', '1000');
gui.saveDeposit('token2', '5000');

const approvalCalldatas: ApprovalCalldataResult = await gui.generateApprovalCalldatas(
const result = await gui.generateApprovalCalldatas(
'0x1234567890abcdef1234567890abcdef12345678'
);
assert.equal(approvalCalldatas.length, 1);
assert.equal(approvalCalldatas[0].token, '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063');
// 5000 - 1000 = 4000 * 10^18

assert.equal(result.Calldatas.length, 1);
assert.equal(result.Calldatas[0].token, '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063');
assert.equal(
approvalCalldatas[0].calldata,
result.Calldatas[0].calldata,
'0x095ea7b3000000000000000000000000c95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a600000000000000000000000000000000000000000000010f0cf064dd59200000'
);

// Test no deposits case
gui.removeDeposit('token1');
gui.removeDeposit('token2');
const emptyResult = await gui.generateApprovalCalldatas(
'0x1234567890abcdef1234567890abcdef12345678'
);
assert.equal(emptyResult, 'NoDeposits');
});

it('generates deposit calldatas', async () => {
Expand Down Expand Up @@ -926,12 +934,19 @@ ${dotrainWithoutVaultIds}
gui.saveDeposit('token1', '1000');
gui.saveDeposit('token2', '5000');

const depositCalldatas: DepositCalldataResult = await gui.generateDepositCalldatas();
assert.equal(depositCalldatas.length, 1);
const result = await gui.generateDepositCalldatas();

assert.equal(result.Calldatas.length, 1);
assert.equal(
depositCalldatas[0],
result.Calldatas[0],
'0x91337c0a0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000010f0cf064dd5920000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000'
);

// Test no deposits case
gui.removeDeposit('token1');
gui.removeDeposit('token2');
const emptyResult = await gui.generateDepositCalldatas();
assert.equal(emptyResult, 'NoDeposits');
});

it('generates add order calldata', async () => {
Expand Down Expand Up @@ -1035,7 +1050,7 @@ ${dotrainWithoutVaultIds}
.once()
.withBodyIncluding('0x82ad56cb')
.thenSendJsonRpcResult(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
);

let testDotrain = `${guiConfig2}
Expand Down Expand Up @@ -1121,7 +1136,7 @@ ${dotrainWithoutVaultIds}`;
.once()
.withBodyIncluding('0x82ad56cb')
.thenSendJsonRpcResult(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
);

let testDotrain = `${guiConfig2}
Expand All @@ -1144,44 +1159,6 @@ ${dotrainWithoutVaultIds}`;
assert.equal(missingFieldValues[0], 'Test binding');
});

it('should throw error if deposit value not set', async () => {
await mockServer
.forPost('/rpc-url')
.once()
.withBodyIncluding('0x82ad56cb')
.thenSendJsonRpcResult(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007546f6b656e203100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025431000000000000000000000000000000000000000000000000000000000000'
);
await mockServer
.forPost('/rpc-url')
.once()
.withBodyIncluding('0x82ad56cb')
.thenSendJsonRpcResult(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000'
);

let testDotrain = `${guiConfig2}
${dotrainWithoutVaultIds}`;
let gui = await DotrainOrderGui.chooseDeployment(testDotrain, 'other-deployment');

await expect(
async () =>
await gui.generateApprovalCalldatas('0x1234567890abcdef1234567890abcdef12345678')
).rejects.toThrow('Missing deposit with token: T1');
await expect(async () => await gui.generateDepositCalldatas()).rejects.toThrow(
'Missing deposit with token: T1'
);
await expect(async () => await gui.generateDepositAndAddOrderCalldatas()).rejects.toThrow(
'Missing deposit with token: T1'
);

let missingDeposits = gui.getMissingDeposits();
assert.equal(missingDeposits.length, 2);
assert.equal(missingDeposits[0], 'token1');
assert.equal(missingDeposits[1], 'token2');
});

it('should set vault ids', async () => {
mockServer
.forPost('/rpc-url')
Expand Down Expand Up @@ -1250,7 +1227,7 @@ ${dotrainWithoutVaultIds}`;
gui.saveDeposit('token1', '0');
gui.saveDeposit('token2', '0');
const calldatas = await gui.generateDepositCalldatas();
assert.equal(calldatas.length, 0);
assert.equal(calldatas.Calldatas.length, 0);
});
});

Expand Down
Loading

0 comments on commit a39712a

Please sign in to comment.