Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2dc6ef5
Setup notifiy arbiter for hot cold wallet proxy
matthewjablack May 20, 2020
6f16dfc
Add proxy for Loans.approve and Loans.request
matthewjablack May 20, 2020
40c00a0
Add proxy for accept or cancel
matthewjablack May 20, 2020
f651a05
Get E2E tests working
matthewjablack May 22, 2020
0e5081d
Finalize hot cold wallet proxy and test
matthewjablack May 23, 2020
28b83c3
Fix check agent for proxy enabled
matthewjablack May 23, 2020
2fd1852
Fix logging for agent inactive on updating
matthewjablack May 23, 2020
b4db195
Add HOT_COLD_WALLET_PROXY_ENABLED env value to app.json
matthewjablack May 24, 2020
53faf77
Ensure uniqueness of contract address for hot cold wallet proxy schema
matthewjablack May 24, 2020
48c7c29
Ensure record of agent is created before proxy deployed
matthewjablack May 26, 2020
04c21fd
Fix second countdown for sales test getting secret
matthewjablack May 26, 2020
b339880
Fix second countdown for second sales test getting secret
matthewjablack May 26, 2020
7409b06
Fix gas price increase
matthewjablack May 26, 2020
e979bec
Improve error for auto update
matthewjablack May 27, 2020
e2a0dcc
Fix bumpTxFee test
matthewjablack May 27, 2020
4e31efb
Add withdraw txs, api and job
matthewjablack May 31, 2020
d65dac5
Update to 0.2.0
matthewjablack May 31, 2020
566a24c
Add logging to check-agent job
matthewjablack May 31, 2020
c40abda
Add additional logging for agent fund
matthewjablack May 31, 2020
39cd849
Add check agent job error logging
matthewjablack May 31, 2020
dddcc24
Ensure principal address is defined for check agent fund job
matthewjablack Jun 1, 2020
410b162
Add error logging revert init liquidation job
matthewjablack Jun 1, 2020
669b1e6
Add additional error logging for revert job
matthewjablack Jun 1, 2020
df28637
Fix principal address for proxy not enabled
matthewjablack Jun 1, 2020
e9543bf
Improve logging for check-agent agent funds
matthewjablack Jun 1, 2020
418343a
Set min confs 0 for kovan
matthewjablack Jun 17, 2020
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
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ jobs:
- stage: Test E2E
script:
- CI=false npm run test:lender:e2e
- stage: Test Funds
script:
- CI=false npm run test:lender:funds
- stage: Test Loans
script:
- CI=false npm run test:lender:loans
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [0.2.0](https://github.com/AtomicLoans/agent/compare/v0.1.59...v0.2.0) - 2020-05-31

- Add hot/cold wallet

## [0.1.59](https://github.com/AtomicLoans/agent/compare/v0.1.58...v0.1.59) - 2020-04-03

- Add signature checks
Expand Down
5 changes: 5 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
"BUGSNAG_API": {
"description": "Error monitoring",
"required": true
},
"HOT_COLD_WALLET_PROXY_ENABLED": {
"description": "Setup proxy to allow only cold wallet to withdraw funds",
"required": true,
"value": "true"
}
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "atomicagent",
"version": "0.1.59",
"version": "0.2.0",
"description": "Atomic Swap Agent",
"main": "src/index.js",
"scripts": {
Expand Down Expand Up @@ -33,6 +33,7 @@
"test:lender:collateral": "mocha test/loan/lender/collateral $npm_package_options_mocha",
"test:lender:e2e": "mocha test/loan/lender/e2e $npm_package_options_mocha",
"test:lender:tx": "mocha test/loan/lender/tx $npm_package_options_mocha",
"test:lender:proxy": "mocha test/loan/lender/proxy $npm_package_options_mocha",
"test:arbiter:agents": "mocha test/loan/arbiter/agents $npm_package_options_mocha",
"test:modules": "nyc mocha test/loan/modules $npm_package_options_mocha",
"deploy:fund": "mocha test/loan/lender/deploy/fund $npm_package_options_mocha",
Expand Down
8,679 changes: 8,679 additions & 0 deletions src/abi/hotcoldwallet.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/api/routes/loan/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@ function defineAgentRoutes (router) {
const { body } = req
const { signature, message, timestamp } = body

const { data: { principalAddress: arbiterAddress } } = await axios.get(`${getEndpoint('ARBITER_ENDPOINT')}/agentinfo/ticker/USDC/BTC`)
const { data: { principalAgentAddress: arbiterAddress } } = await axios.get(`${getEndpoint('ARBITER_ENDPOINT')}/agentinfo/ticker/USDC/BTC`)
const loanMarket = await LoanMarket.findOne().exec()
const { principalAddress } = await loanMarket.getAgentAddresses()
const { principalAgentAddress } = await loanMarket.getAgentAddresses()

const currentTime = Math.floor(new Date().getTime() / 1000)
if (!verifySignature(signature, message, arbiterAddress)) return next(res.createError(401, 'Signature verification failed'))
if (!(message === `Arbiter force update ${principalAddress} at ${timestamp}`)) return next(res.createError(401, 'Message doesn\'t match params'))
if (!(message === `Arbiter force update ${principalAgentAddress} at ${timestamp}`)) return next(res.createError(401, 'Message doesn\'t match params'))
if (!(currentTime <= (timestamp + 60))) return next(res.createError(401, 'Signature is stale'))
if (!(currentTime >= (timestamp - 120))) return next(res.createError(401, 'Timestamp is too far ahead in the future'))
if (!(typeof timestamp === 'number')) return next(res.createError(401, 'Timestamp is not a number'))
Expand Down
172 changes: 135 additions & 37 deletions src/api/routes/loan/arbiter/agents.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ function defineAgentsRouter (router) {
router.post('/agents/new', asyncHandler(async (req, res, next) => {
console.log('start /agents/new')
const { body } = req
const { ethSigner, principalAddress, collateralPublicKey, url, signature, timestamp } = body
const { ethSigner, principalAddress, collateralPublicKey, url, signature, timestamp, proxyEnabled, principalAgentAddress } = body

try {
verifyTimestampedSignatureUsingExpected(signature, `Register new agent (${principalAddress} ${collateralPublicKey} ${ethSigner} ${url}) ${timestamp}`, timestamp, principalAddress)
if (proxyEnabled) {
verifyTimestampedSignatureUsingExpected(signature, `Register new agent (${principalAgentAddress} ${collateralPublicKey} ${ethSigner} ${url}) ${timestamp}`, timestamp, principalAgentAddress)
} else {
verifyTimestampedSignatureUsingExpected(signature, `Register new agent (${principalAddress} ${collateralPublicKey} ${ethSigner} ${url}) ${timestamp}`, timestamp, principalAddress)
}
} catch (e) {
return next(res.createError(401, e.message))
}
Expand All @@ -26,44 +30,138 @@ function defineAgentsRouter (router) {

try {
const { status, data: loanMarkets } = await axios.get(`${url}/loanmarketinfo`)
console.log('status', status)
console.log('loanMarkets', loanMarkets)

if (status === 200) {
const { data: agent } = await axios.get(`${url}/agentinfo/${loanMarkets[0].id}`)
const { data: { version } } = await axios.get(`${url}/version`)
console.log('agent', agent)

const agentWithUrlExists = await Agent.findOne({ url }).exec()
const agentWithEthSignerExists = await Agent.findOne({ ethSigner }).exec()
const agentWithPrincipalAddressExists = await Agent.findOne({ principalAddress }).exec()

if (!agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAddressExists) {
const ethBalance = await web3().eth.getBalance(principalAddress)
const params = { ethSigner, principalAddress, collateralPublicKey, url, endpoint, ethBalance: fromWei(ethBalance.toString(), 'ether'), version }
const agent = Agent.fromAgentParams(params)
await agent.save()
res.json(agent.json())
} else if (!agentWithUrlExists && !agentWithEthSignerExists && agentWithPrincipalAddressExists) {
agentWithPrincipalAddressExists.url = url
agentWithPrincipalAddressExists.ethSigner = ethSigner
await agentWithPrincipalAddressExists.save()
res.json(agentWithPrincipalAddressExists.json())
} else if (!agentWithUrlExists && agentWithEthSignerExists && !agentWithPrincipalAddressExists) {
agentWithEthSignerExists.url = url
agentWithEthSignerExists.principalAddress = principalAddress
agentWithEthSignerExists.collateralPublicKey = collateralPublicKey
await agentWithEthSignerExists.save()
res.json(agentWithEthSignerExists.json())
} else if (agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAddressExists) {
agentWithUrlExists.ethSigner = ethSigner
agentWithUrlExists.principalAddress = principalAddress
agentWithUrlExists.collateralPublicKey = collateralPublicKey
await agentWithUrlExists.save()
res.json(agentWithUrlExists.json())
} else {
res.json(agentWithUrlExists.json())
for (const loanMarket of loanMarkets) {
const { principal, collateral } = loanMarket

const { data: agent } = await axios.get(`${url}/agentinfo/${loanMarket.id}`)
const { data: { version } } = await axios.get(`${url}/version`)

const { principalAddress: loanMarketPrincipalAddress, proxyEnabled: agentProxyEnabled } = agent
if (agentProxyEnabled) {
// if proxy is enabled check if principal address is set
// find agent by url, ethSigner and principalAgentAddress
if (loanMarketPrincipalAddress) {
const agentWithUrlExists = await Agent.findOne({ url }).exec()
const agentWithEthSignerExists = await Agent.findOne({ ethSigner }).exec()
const agentWithPrincipalAgentAddressExists = await Agent.findOne({ principalAgentAddress }).exec()

if (!agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAgentAddressExists) {
// define principal addresses
const ethBalance = await web3().eth.getBalance(principalAgentAddress)
const params = { ethSigner, principalAddress: loanMarketPrincipalAddress, principalAgentAddress, collateralPublicKey, url, endpoint, ethBalance: fromWei(ethBalance.toString(), 'ether'), version, proxyEnabled: agentProxyEnabled }
const agent = Agent.fromAgentParams(params)

// update agent principalAddresses
agent.principalAddresses = [{ principal, collateral, principalAddress: loanMarketPrincipalAddress }]
await agent.save()
} else if (!agentWithUrlExists && !agentWithEthSignerExists && agentWithPrincipalAgentAddressExists) {
agentWithPrincipalAgentAddressExists.url = url
agentWithPrincipalAgentAddressExists.ethSigner = ethSigner
let found = false
for (let i = 0; i < agentWithPrincipalAgentAddressExists.principalAddresses.length; i++) {
if (agentWithPrincipalAgentAddressExists.principalAddresses[i].principal === principal) {
found = true
}
}
if (!found) {
const currentPrincipalAddresses = agentWithPrincipalAgentAddressExists.principalAddresses
currentPrincipalAddresses.push({ principal, collateral, principalAddress: loanMarketPrincipalAddress })
agentWithPrincipalAgentAddressExists.principalAddress = currentPrincipalAddresses
}
await agentWithPrincipalAgentAddressExists.save()
} else if (!agentWithUrlExists && agentWithEthSignerExists && !agentWithPrincipalAgentAddressExists) {
agentWithEthSignerExists.url = url
agentWithEthSignerExists.principalAddress = principalAddress
agentWithEthSignerExists.principalAgentAddress = principalAgentAddress
agentWithEthSignerExists.collateralPublicKey = collateralPublicKey
await agentWithEthSignerExists.save()
} else if (agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAgentAddressExists) {
agentWithUrlExists.ethSigner = ethSigner
agentWithUrlExists.principalAddress = principalAddress
agentWithUrlExists.principalAgentAddress = principalAgentAddress
agentWithUrlExists.collateralPublicKey = collateralPublicKey
await agentWithUrlExists.save()
} else {
const agentModel = await Agent.findOne({ url }).exec()

let principalAddressFound = false
let principalAddresses = agentModel.principalAddresses
for (let i = 0; i < principalAddresses.length; i++) {
if (principalAddresses[i].principal === principal) {
principalAddressFound = true
}
}

if (!principalAddressFound) {
principalAddresses = principalAddresses.push({ principal, collateral, principalAddress: loanMarketPrincipalAddress })
if (agentModel.principalAddress === undefined || agentModel.principalAddress === 'undefined') { // Set principalAddress to proxy address for backwards compatibility
agentModel.principalAddress = loanMarketPrincipalAddress
}
}

await agentModel.save()
}
} else {
const agentWithUrlExists = await Agent.findOne({ url }).exec()
const agentWithEthSignerExists = await Agent.findOne({ ethSigner }).exec()
const agentWithPrincipalAgentAddressExists = await Agent.findOne({ principalAgentAddress }).exec()

if (!agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAgentAddressExists) {
const ethBalance = await web3().eth.getBalance(principalAgentAddress)
const params = { ethSigner, principalAddress: undefined, principalAgentAddress, collateralPublicKey, url, endpoint, ethBalance: fromWei(ethBalance.toString(), 'ether'), version, proxyEnabled: agentProxyEnabled }
const agent = Agent.fromAgentParams(params)
await agent.save()
} else if (!agentWithUrlExists && !agentWithEthSignerExists && agentWithPrincipalAgentAddressExists) {
agentWithPrincipalAgentAddressExists.url = url
agentWithPrincipalAgentAddressExists.ethSigner = ethSigner
await agentWithPrincipalAgentAddressExists.save()
} else if (!agentWithUrlExists && agentWithEthSignerExists && !agentWithPrincipalAgentAddressExists) {
agentWithEthSignerExists.url = url
agentWithEthSignerExists.principalAgentAddress = principalAgentAddress
agentWithEthSignerExists.collateralPublicKey = collateralPublicKey
await agentWithEthSignerExists.save()
} else if (agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAgentAddressExists) {
agentWithUrlExists.ethSigner = ethSigner
agentWithUrlExists.principalAddress = principalAddress
agentWithUrlExists.principalAgentAddress = principalAgentAddress
agentWithUrlExists.collateralPublicKey = collateralPublicKey
await agentWithUrlExists.save()
}
}
} else {
const agentWithUrlExists = await Agent.findOne({ url }).exec()
const agentWithEthSignerExists = await Agent.findOne({ ethSigner }).exec()
const agentWithPrincipalAddressExists = await Agent.findOne({ principalAddress }).exec()

if (!agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAddressExists) {
const ethBalance = await web3().eth.getBalance(principalAddress)
const params = { ethSigner, principalAddress, principalAgentAddress: principalAddress, collateralPublicKey, url, endpoint, ethBalance: fromWei(ethBalance.toString(), 'ether'), version, proxyEnabled: false }
const agent = Agent.fromAgentParams(params)
await agent.save()
} else if (!agentWithUrlExists && !agentWithEthSignerExists && agentWithPrincipalAddressExists) {
agentWithPrincipalAddressExists.url = url
agentWithPrincipalAddressExists.ethSigner = ethSigner
await agentWithPrincipalAddressExists.save()
} else if (!agentWithUrlExists && agentWithEthSignerExists && !agentWithPrincipalAddressExists) {
agentWithEthSignerExists.url = url
agentWithEthSignerExists.principalAddress = principalAddress
agentWithEthSignerExists.principalAgentAddress = principalAgentAddress
agentWithEthSignerExists.collateralPublicKey = collateralPublicKey
await agentWithEthSignerExists.save()
} else if (agentWithUrlExists && !agentWithEthSignerExists && !agentWithPrincipalAddressExists) {
agentWithUrlExists.ethSigner = ethSigner
agentWithUrlExists.principalAddress = principalAddress
agentWithUrlExists.principalAgentAddress = principalAgentAddress
agentWithUrlExists.collateralPublicKey = collateralPublicKey
await agentWithUrlExists.save()
}
}
}

const updatedAgent = await Agent.findOne({ url }).exec()
res.json(updatedAgent.json())
} else { return next(res.createError(401, 'Url Invalid or Lender Agent offline')) }
} catch (e) {
console.log('Error:', e)
Expand Down
6 changes: 1 addition & 5 deletions src/api/routes/loan/arbiter/liquidators.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,10 @@ function defineLiquidatorsRouter (router) {
}

try {
const { status, data: loanMarkets } = await axios.get(`${url}/loanmarketinfo`)
console.log('status', status)
console.log('loanMarkets', loanMarkets)
const { status } = await axios.get(`${url}/loanmarketinfo`)

if (status === 200) {
const { data: agent } = await axios.get(`${url}/agentinfo/${loanMarkets[0].id}`)
const { data: { version } } = await axios.get(`${url}/version`)
console.log('agent', agent)

const agentWithUrlExists = await Liquidator.findOne({ url }).exec()
const agentWithEthSignerExists = await Liquidator.findOne({ ethSigner }).exec()
Expand Down
2 changes: 0 additions & 2 deletions src/api/routes/loan/arbiter/sales.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ function defineSalesRouter (router) {
const { body } = req
const { principal, loanId, lenderSigs, refundableAmount, seizableAmount, signature, address, timestamp } = body

console.log('principal, loanId, lenderSigs, refundableAmount, seizableAmount, signature, address, timestamp', principal, loanId, lenderSigs, refundableAmount, seizableAmount, signature, address, timestamp)

try {
verifyTimestampedSignatureUsingExpected(signature, `New sale (${principal} ${loanId} ${stringify(lenderSigs)} ${refundableAmount} ${seizableAmount}) ${timestamp}`, timestamp, address)
} catch (e) {
Expand Down
Loading