@connext/apps
Advanced tools
Comparing version 6.0.0-alpha3 to 6.0.1
this.window = this.window || {}; | ||
this.window.apps = (function (exports, types, cfCore, constants, utils, contracts) { | ||
this.window.apps = (function (exports, types, utils, constants, contracts, ethers, utils$1, cfCore) { | ||
'use strict'; | ||
const CoinBalanceRefundAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: types.CoinBalanceRefundAppName, | ||
outcomeType: types.OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: types.CoinBalanceRefundAppStateEncoding, | ||
}; | ||
const FastSignedTransferAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: types.FastSignedTransferAppName, | ||
outcomeType: types.OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: types.FastSignedTransferAppStateEncoding, | ||
actionEncoding: types.FastSignedTransferAppActionEncoding, | ||
}; | ||
const SupportedApplications = types.enumify({ | ||
[types.CoinBalanceRefundAppName]: types.CoinBalanceRefundAppName, | ||
[types.SimpleLinkedTransferAppName]: types.SimpleLinkedTransferAppName, | ||
[types.SimpleSignedTransferAppName]: types.SimpleSignedTransferAppName, | ||
[types.SimpleTwoPartySwapAppName]: types.SimpleTwoPartySwapAppName, | ||
[types.FastSignedTransferAppName]: types.FastSignedTransferAppName, | ||
[types.WithdrawAppName]: types.WithdrawAppName, | ||
[types.HashLockTransferAppName]: types.HashLockTransferAppName, | ||
[types.DepositAppName]: types.DepositAppName, | ||
}); | ||
const DEFAULT_APP_TIMEOUT = utils.toBN(8640); | ||
@@ -33,3 +18,3 @@ const appProposalMatchesRegistry = (proposal, appRegistryInfo) => { | ||
proposal.abiEncodings.stateEncoding === appRegistryInfo.stateEncoding))) { | ||
throw new Error(`Proposed app details ${types.stringify(proposal)} do not match registry ${types.stringify(appRegistryInfo)}`); | ||
throw new Error(`Proposed app details ${utils.stringify(proposal)} do not match registry ${utils.stringify(appRegistryInfo)}`); | ||
} | ||
@@ -62,13 +47,16 @@ }; | ||
const commonAppProposalValidation = (params, appRegistryInfo, supportedTokenAddresses) => { | ||
const { initiatorDeposit, initiatorDepositTokenAddress, responderDeposit, responderDepositTokenAddress, } = params; | ||
const { initiatorDeposit, initiatorDepositAssetId, responderDeposit, responderDepositAssetId, } = params; | ||
appProposalMatchesRegistry(params, appRegistryInfo); | ||
const initiatorDepositTokenAddress = utils.getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = utils.getAddressFromAssetId(responderDepositAssetId); | ||
if (!supportedTokenAddresses.includes(initiatorDepositTokenAddress)) { | ||
throw new Error(`Unsupported "initiatorDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported initiatorDepositTokenAddress: ${initiatorDepositTokenAddress}`); | ||
} | ||
if (!supportedTokenAddresses.includes(responderDepositTokenAddress)) { | ||
throw new Error(`Unsupported "responderDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported responderDepositAssetId: ${responderDepositTokenAddress}`); | ||
} | ||
const isDeposit = appRegistryInfo.name === types.DepositAppName; | ||
if (responderDeposit.isZero() && | ||
initiatorDeposit.isZero() && | ||
appRegistryInfo.name !== types.CoinBalanceRefundAppName) { | ||
!isDeposit) { | ||
throw new Error(`Cannot install an app with zero valued deposits for both initiator and responder.`); | ||
@@ -78,18 +66,76 @@ } | ||
const validateFastSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const DepositAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: types.DepositAppName, | ||
outcomeType: types.OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: types.DepositAppStateEncoding, | ||
}; | ||
const DEPOSIT_STATE_TIMEOUT = DEFAULT_APP_TIMEOUT; | ||
const validateDepositApp = async (params, initiatorIdentifier, responderIdentifier, multisigAddress, provider) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
if (initialState.paymentId !== constants.HashZero) { | ||
throw new Error(`Cannot install with pre-populated paymentId`); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
const responderTransfer = initialState.transfers[1]; | ||
baseCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (initiatorSignerAddress !== initiatorTransfer.to) { | ||
throw new Error(`Cannot install deposit app with incorrect initiator transfer to address: Expected ${initiatorSignerAddress}, got ${initiatorTransfer.to}`); | ||
} | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
})[0]; | ||
unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (responderSignerAddress !== responderTransfer.to) { | ||
throw new Error(`Cannot install deposit app with incorrect responder transfer to address: Expected ${responderSignerAddress}, got ${responderTransfer.to}`); | ||
} | ||
if (!initialState.transfers[0].amount.isZero() || !initialState.transfers[1].amount.isZero()) { | ||
throw new Error(`Cannot install deposit app with nonzero initial balance: ${utils.stringify(initialState.transfers)}`); | ||
} | ||
if (initialState.multisigAddress !== multisigAddress) { | ||
throw new Error(`Cannot install deposit app with invalid multisig address. Expected ${multisigAddress}, got ${initialState.multisigAddress}`); | ||
} | ||
if (initialState.assetId !== utils.getAddressFromAssetId(params.initiatorDepositAssetId) | ||
|| initialState.assetId !== utils.getAddressFromAssetId(params.responderDepositAssetId)) { | ||
throw new Error(`Cannot install deposit app with invalid token address. Expected ${utils.getAddressFromAssetId(params.initiatorDepositAssetId)}, got ${initialState.assetId}`); | ||
} | ||
const startingMultisigBalance = initialState.assetId === types.CONVENTION_FOR_ETH_ASSET_ID | ||
? await provider.getBalance(multisigAddress) | ||
: await new ethers.Contract(initialState.assetId, contracts.ERC20.abi, provider) | ||
.functions | ||
.balanceOf(multisigAddress); | ||
const multisig = new ethers.Contract(multisigAddress, contracts.MinimumViableMultisig.abi, provider); | ||
let startingTotalAmountWithdrawn; | ||
try { | ||
startingTotalAmountWithdrawn = await multisig | ||
.functions | ||
.totalAmountWithdrawn(initialState.assetId); | ||
} | ||
catch (e) { | ||
const NOT_DEPLOYED_ERR = `contract not deployed (contractAddress="${multisigAddress}"`; | ||
if (!e.message.includes(NOT_DEPLOYED_ERR)) { | ||
throw new Error(e); | ||
} | ||
startingTotalAmountWithdrawn = constants.Zero; | ||
} | ||
if (!initialState.startingTotalAmountWithdrawn.eq(startingTotalAmountWithdrawn)) { | ||
throw new Error(`Cannot install deposit app with invalid totalAmountWithdrawn. Expected ${startingTotalAmountWithdrawn}, got ${initialState.startingTotalAmountWithdrawn}`); | ||
} | ||
if (!initialState.startingMultisigBalance.eq(startingMultisigBalance)) { | ||
throw new Error(`Cannot install deposit app with invalid startingMultisigBalance. Expected ${startingMultisigBalance}, got ${initialState.startingMultisigBalance}`); | ||
} | ||
}; | ||
const uninstallDepositMiddleware = async (context, provider) => { | ||
const { role, appInstance, stateChannel, params, } = context; | ||
const latestState = appInstance.latestState; | ||
const currentMultisigBalance = latestState.assetId === types.CONVENTION_FOR_ETH_ASSET_ID | ||
? await provider.getBalance(stateChannel.multisigAddress) | ||
: await new ethers.Contract(latestState.assetId, contracts.ERC20.abi, provider) | ||
.functions | ||
.balanceOf(stateChannel.multisigAddress); | ||
if (currentMultisigBalance.lt(latestState.startingMultisigBalance)) { | ||
throw new Error(`Refusing to uninstall, current multisig balance (${currentMultisigBalance.toString()}) is less than starting multsig balance (${latestState.startingMultisigBalance.toString()})`); | ||
} | ||
if (role === types.ProtocolRoles.initiator | ||
&& latestState.transfers[0].to !== utils.getSignerAddressFromPublicIdentifier(params.initiatorIdentifier)) { | ||
throw new Error(`Cannot uninstall deposit app without being the initiator`); | ||
} | ||
}; | ||
@@ -103,13 +149,14 @@ const HashLockTransferAppRegistryInfo = { | ||
}; | ||
const HASHLOCK_TRANSFER_STATE_TIMEOUT = constants.Zero; | ||
const validateHashLockTransferApp = (params, blockNumber, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateHashLockTransferApp = (params, blockNumber, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -129,17 +176,18 @@ if (initialState.timelock.lt(blockNumber)) { | ||
}; | ||
const LINKED_TRANSFER_STATE_TIMEOUT = constants.Zero; | ||
const validateSimpleLinkedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateSimpleLinkedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (!initialState.amount.eq(initiatorDeposit)) { | ||
throw new Error(`Payment amount bust be the same as initiator deposit ${types.stringify(params)}`); | ||
throw new Error(`Payment amount bust be the same as initiator deposit ${utils.stringify(params)}`); | ||
} | ||
@@ -155,13 +203,14 @@ }; | ||
}; | ||
const SIGNED_TRANSFER_STATE_TIMEOUT = constants.Zero; | ||
const validateSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateSignedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -177,13 +226,16 @@ unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
}; | ||
const SWAP_STATE_TIMEOUT = constants.Zero; | ||
const ALLOWED_DISCREPANCY_PCT = 5; | ||
const validateSimpleSwapApp = (params, allowedSwaps, ourRate) => { | ||
const { responderDeposit, initiatorDeposit, initiatorDepositTokenAddress, responderDepositTokenAddress, } = params; | ||
const { responderDeposit, initiatorDeposit, initiatorDepositAssetId, responderDepositAssetId, } = params; | ||
const initiatorDepositTokenAddress = utils.getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = utils.getAddressFromAssetId(responderDepositAssetId); | ||
if (!allowedSwaps.find((swap) => swap.from === initiatorDepositTokenAddress && swap.to === responderDepositTokenAddress)) { | ||
throw new Error(`Swap from ${initiatorDepositTokenAddress} to ${responderDepositTokenAddress} is not valid. Valid swaps: ${types.stringify(allowedSwaps)}`); | ||
throw new Error(`Swap from ${initiatorDepositTokenAddress} to ${responderDepositTokenAddress} is not valid. Valid swaps: ${utils.stringify(allowedSwaps)}`); | ||
} | ||
const calculated = types.calculateExchange(initiatorDeposit, ourRate); | ||
const calculated = utils.calculateExchange(initiatorDeposit, ourRate); | ||
const calculatedToActualDiscrepancy = calculated.sub(responderDeposit).abs(); | ||
const allowedDiscrepancy = calculated | ||
.mul(utils.bigNumberify(100).sub(ALLOWED_DISCREPANCY_PCT)) | ||
.mul(utils$1.bigNumberify(100).sub(ALLOWED_DISCREPANCY_PCT)) | ||
.div(100); | ||
@@ -202,8 +254,9 @@ if (calculatedToActualDiscrepancy.gt(allowedDiscrepancy)) { | ||
}; | ||
const WITHDRAW_STATE_TIMEOUT = constants.Zero; | ||
const validateWithdrawApp = async (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateWithdrawApp = async (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = types.bigNumberifyJson(params.initialState); | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initialState = utils.bigNumberifyJson(params.initialState); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
@@ -218,4 +271,4 @@ const responderTransfer = initialState.transfers[1]; | ||
} | ||
if (initialState.signers[0] !== initiatorFreeBalanceAddress || | ||
initialState.signers[1] !== responderFreeBalanceAddress) { | ||
if (initialState.signers[0] !== initiatorSignerAddress || | ||
initialState.signers[1] !== responderSignerAddress) { | ||
throw new Error(`Cannot install a withdraw app if signers[] do not match multisig participant addresses. Signers[]: ${initialState.signers}`); | ||
@@ -226,3 +279,3 @@ } | ||
} | ||
let recovered = await types.recoverAddressWithEthers(initialState.data, initialState.signatures[0]); | ||
let recovered = await utils.verifyChannelMessage(initialState.data, initialState.signatures[0]); | ||
if (recovered !== initialState.signers[0]) { | ||
@@ -234,52 +287,84 @@ throw new Error(`Cannot install withdraw app - incorrect signer recovered from initiator sig on data. | ||
class WithdrawETHCommitment extends cfCore.MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value) { | ||
const iface = new utils$1.Interface(contracts.ConditionalTransactionDelegateTarget.abi); | ||
class WithdrawCommitment extends cfCore.MultisigCommitment { | ||
constructor(networkContext, multisigAddress, multisigOwners, recipient, assetId, amount, nonce) { | ||
super(multisigAddress, multisigOwners); | ||
this.networkContext = networkContext; | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.recipient = recipient; | ||
this.assetId = assetId; | ||
this.amount = amount; | ||
this.nonce = nonce; | ||
} | ||
getTransactionDetails() { | ||
return { | ||
to: this.to, | ||
value: utils.bigNumberify(this.value), | ||
data: "0x", | ||
operation: types.MultisigOperation.Call, | ||
to: this.networkContext.ConditionalTransactionDelegateTarget, | ||
value: 0, | ||
data: iface.functions.withdrawWrapper.encode([ | ||
this.recipient, | ||
this.assetId, | ||
this.amount, | ||
this.nonce, | ||
]), | ||
operation: types.MultisigOperation.DelegateCall, | ||
}; | ||
} | ||
} | ||
class WithdrawERC20Commitment extends cfCore.MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value, tokenAddress) { | ||
super(multisigAddress, multisigOwners); | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.tokenAddress = tokenAddress; | ||
const generateValidationMiddleware = async (contracts) => { | ||
if (!contracts.provider) { | ||
throw new Error(`Validation middleware needs access to a provider`); | ||
} | ||
getTransactionDetails() { | ||
return { | ||
data: new utils.Interface(contracts.ERC20.abi).functions.transfer.encode([this.to, this.value]), | ||
operation: types.MultisigOperation.Call, | ||
to: this.tokenAddress, | ||
value: 0, | ||
}; | ||
const validationMiddleware = async (protocol, middlewareContext) => { | ||
switch (protocol) { | ||
case (types.ProtocolNames.setup): | ||
case (types.ProtocolNames.propose): | ||
case (types.ProtocolNames.install): | ||
case (types.ProtocolNames.update): | ||
case (types.ProtocolNames.takeAction): { | ||
break; | ||
} | ||
case (types.ProtocolNames.uninstall): { | ||
await uninstallMiddleware(contracts, middlewareContext); | ||
break; | ||
} | ||
default: | ||
throw new Error(`Unrecognized protocol name: ${protocol}`); | ||
} | ||
}; | ||
return validationMiddleware; | ||
}; | ||
const uninstallMiddleware = async (contracts, middlewareContext) => { | ||
const { appInstance } = middlewareContext; | ||
const appDef = appInstance.appInterface.addr; | ||
switch (appDef) { | ||
case (contracts.DepositApp): { | ||
await uninstallDepositMiddleware(middlewareContext, contracts.provider); | ||
break; | ||
} | ||
default: { | ||
return; | ||
} | ||
} | ||
} | ||
}; | ||
const AppRegistry = [ | ||
FastSignedTransferAppRegistryInfo, | ||
SimpleLinkedTransferAppRegistryInfo, | ||
SimpleSignedTransferAppRegistryInfo, | ||
SimpleTwoPartySwapAppRegistryInfo, | ||
CoinBalanceRefundAppRegistryInfo, | ||
WithdrawAppRegistryInfo, | ||
HashLockTransferAppRegistryInfo, | ||
DepositAppRegistryInfo, | ||
]; | ||
exports.AppRegistry = AppRegistry; | ||
exports.CoinBalanceRefundAppRegistryInfo = CoinBalanceRefundAppRegistryInfo; | ||
exports.FastSignedTransferAppRegistryInfo = FastSignedTransferAppRegistryInfo; | ||
exports.DEFAULT_APP_TIMEOUT = DEFAULT_APP_TIMEOUT; | ||
exports.DEPOSIT_STATE_TIMEOUT = DEPOSIT_STATE_TIMEOUT; | ||
exports.DepositAppRegistryInfo = DepositAppRegistryInfo; | ||
exports.HASHLOCK_TRANSFER_STATE_TIMEOUT = HASHLOCK_TRANSFER_STATE_TIMEOUT; | ||
exports.HashLockTransferAppRegistryInfo = HashLockTransferAppRegistryInfo; | ||
exports.LINKED_TRANSFER_STATE_TIMEOUT = LINKED_TRANSFER_STATE_TIMEOUT; | ||
exports.SIGNED_TRANSFER_STATE_TIMEOUT = SIGNED_TRANSFER_STATE_TIMEOUT; | ||
exports.SWAP_STATE_TIMEOUT = SWAP_STATE_TIMEOUT; | ||
exports.SimpleLinkedTransferAppRegistryInfo = SimpleLinkedTransferAppRegistryInfo; | ||
@@ -289,9 +374,11 @@ exports.SimpleSignedTransferAppRegistryInfo = SimpleSignedTransferAppRegistryInfo; | ||
exports.SupportedApplications = SupportedApplications; | ||
exports.WITHDRAW_STATE_TIMEOUT = WITHDRAW_STATE_TIMEOUT; | ||
exports.WithdrawAppRegistryInfo = WithdrawAppRegistryInfo; | ||
exports.WithdrawERC20Commitment = WithdrawERC20Commitment; | ||
exports.WithdrawETHCommitment = WithdrawETHCommitment; | ||
exports.WithdrawCommitment = WithdrawCommitment; | ||
exports.baseCoinTransferValidation = baseCoinTransferValidation; | ||
exports.commonAppProposalValidation = commonAppProposalValidation; | ||
exports.generateValidationMiddleware = generateValidationMiddleware; | ||
exports.unidirectionalCoinTransferValidation = unidirectionalCoinTransferValidation; | ||
exports.validateFastSignedTransferApp = validateFastSignedTransferApp; | ||
exports.uninstallDepositMiddleware = uninstallDepositMiddleware; | ||
exports.validateDepositApp = validateDepositApp; | ||
exports.validateHashLockTransferApp = validateHashLockTransferApp; | ||
@@ -305,2 +392,2 @@ exports.validateSignedTransferApp = validateSignedTransferApp; | ||
}({}, types, cfCore, constants, utils, contracts)); | ||
}({}, types, utils, constants, contracts, ethers, utils$1, cfCore)); |
@@ -1,31 +0,18 @@ | ||
import { CoinBalanceRefundAppName, OutcomeType, CoinBalanceRefundAppStateEncoding, FastSignedTransferAppName, FastSignedTransferAppStateEncoding, FastSignedTransferAppActionEncoding, enumify, SimpleLinkedTransferAppName, SimpleSignedTransferAppName, SimpleTwoPartySwapAppName, WithdrawAppName, HashLockTransferAppName, stringify, HashLockTransferAppActionEncoding, HashLockTransferAppStateEncoding, SimpleLinkedTransferAppActionEncoding, SimpleLinkedTransferAppStateEncoding, SimpleSignedTransferAppStateEncoding, SimpleSignedTransferAppActionEncoding, SimpleSwapAppStateEncoding, calculateExchange, WithdrawAppStateEncoding, WithdrawAppActionEncoding, bigNumberifyJson, recoverAddressWithEthers, MultisigOperation } from '@connext/types'; | ||
import { xkeyKthAddress, MultisigCommitment } from '@connext/cf-core'; | ||
import { enumify, SimpleLinkedTransferAppName, SimpleSignedTransferAppName, SimpleTwoPartySwapAppName, WithdrawAppName, HashLockTransferAppName, DepositAppName, OutcomeType, DepositAppStateEncoding, CONVENTION_FOR_ETH_ASSET_ID, ProtocolRoles, HashLockTransferAppActionEncoding, HashLockTransferAppStateEncoding, SimpleLinkedTransferAppActionEncoding, SimpleLinkedTransferAppStateEncoding, SimpleSignedTransferAppStateEncoding, SimpleSignedTransferAppActionEncoding, SimpleSwapAppStateEncoding, WithdrawAppStateEncoding, WithdrawAppActionEncoding, MultisigOperation, ProtocolNames } from '@connext/types'; | ||
import { toBN, getAddressFromAssetId, stringify, getSignerAddressFromPublicIdentifier, calculateExchange, bigNumberifyJson, verifyChannelMessage } from '@connext/utils'; | ||
import { Zero, HashZero } from 'ethers/constants'; | ||
import { ERC20, MinimumViableMultisig, ConditionalTransactionDelegateTarget } from '@connext/contracts'; | ||
import { Contract } from 'ethers'; | ||
import { bigNumberify, Interface } from 'ethers/utils'; | ||
import { ERC20 } from '@connext/contracts'; | ||
import { MultisigCommitment } from '@connext/cf-core'; | ||
const CoinBalanceRefundAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: CoinBalanceRefundAppName, | ||
outcomeType: OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: CoinBalanceRefundAppStateEncoding, | ||
}; | ||
const FastSignedTransferAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: FastSignedTransferAppName, | ||
outcomeType: OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: FastSignedTransferAppStateEncoding, | ||
actionEncoding: FastSignedTransferAppActionEncoding, | ||
}; | ||
const SupportedApplications = enumify({ | ||
[CoinBalanceRefundAppName]: CoinBalanceRefundAppName, | ||
[SimpleLinkedTransferAppName]: SimpleLinkedTransferAppName, | ||
[SimpleSignedTransferAppName]: SimpleSignedTransferAppName, | ||
[SimpleTwoPartySwapAppName]: SimpleTwoPartySwapAppName, | ||
[FastSignedTransferAppName]: FastSignedTransferAppName, | ||
[WithdrawAppName]: WithdrawAppName, | ||
[HashLockTransferAppName]: HashLockTransferAppName, | ||
[DepositAppName]: DepositAppName, | ||
}); | ||
const DEFAULT_APP_TIMEOUT = toBN(8640); | ||
@@ -63,13 +50,16 @@ const appProposalMatchesRegistry = (proposal, appRegistryInfo) => { | ||
const commonAppProposalValidation = (params, appRegistryInfo, supportedTokenAddresses) => { | ||
const { initiatorDeposit, initiatorDepositTokenAddress, responderDeposit, responderDepositTokenAddress, } = params; | ||
const { initiatorDeposit, initiatorDepositAssetId, responderDeposit, responderDepositAssetId, } = params; | ||
appProposalMatchesRegistry(params, appRegistryInfo); | ||
const initiatorDepositTokenAddress = getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = getAddressFromAssetId(responderDepositAssetId); | ||
if (!supportedTokenAddresses.includes(initiatorDepositTokenAddress)) { | ||
throw new Error(`Unsupported "initiatorDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported initiatorDepositTokenAddress: ${initiatorDepositTokenAddress}`); | ||
} | ||
if (!supportedTokenAddresses.includes(responderDepositTokenAddress)) { | ||
throw new Error(`Unsupported "responderDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported responderDepositAssetId: ${responderDepositTokenAddress}`); | ||
} | ||
const isDeposit = appRegistryInfo.name === DepositAppName; | ||
if (responderDeposit.isZero() && | ||
initiatorDeposit.isZero() && | ||
appRegistryInfo.name !== CoinBalanceRefundAppName) { | ||
!isDeposit) { | ||
throw new Error(`Cannot install an app with zero valued deposits for both initiator and responder.`); | ||
@@ -79,18 +69,76 @@ } | ||
const validateFastSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const DepositAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: DepositAppName, | ||
outcomeType: OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: DepositAppStateEncoding, | ||
}; | ||
const DEPOSIT_STATE_TIMEOUT = DEFAULT_APP_TIMEOUT; | ||
const validateDepositApp = async (params, initiatorIdentifier, responderIdentifier, multisigAddress, provider) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
if (initialState.paymentId !== HashZero) { | ||
throw new Error(`Cannot install with pre-populated paymentId`); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
const responderTransfer = initialState.transfers[1]; | ||
baseCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (initiatorSignerAddress !== initiatorTransfer.to) { | ||
throw new Error(`Cannot install deposit app with incorrect initiator transfer to address: Expected ${initiatorSignerAddress}, got ${initiatorTransfer.to}`); | ||
} | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
})[0]; | ||
unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (responderSignerAddress !== responderTransfer.to) { | ||
throw new Error(`Cannot install deposit app with incorrect responder transfer to address: Expected ${responderSignerAddress}, got ${responderTransfer.to}`); | ||
} | ||
if (!initialState.transfers[0].amount.isZero() || !initialState.transfers[1].amount.isZero()) { | ||
throw new Error(`Cannot install deposit app with nonzero initial balance: ${stringify(initialState.transfers)}`); | ||
} | ||
if (initialState.multisigAddress !== multisigAddress) { | ||
throw new Error(`Cannot install deposit app with invalid multisig address. Expected ${multisigAddress}, got ${initialState.multisigAddress}`); | ||
} | ||
if (initialState.assetId !== getAddressFromAssetId(params.initiatorDepositAssetId) | ||
|| initialState.assetId !== getAddressFromAssetId(params.responderDepositAssetId)) { | ||
throw new Error(`Cannot install deposit app with invalid token address. Expected ${getAddressFromAssetId(params.initiatorDepositAssetId)}, got ${initialState.assetId}`); | ||
} | ||
const startingMultisigBalance = initialState.assetId === CONVENTION_FOR_ETH_ASSET_ID | ||
? await provider.getBalance(multisigAddress) | ||
: await new Contract(initialState.assetId, ERC20.abi, provider) | ||
.functions | ||
.balanceOf(multisigAddress); | ||
const multisig = new Contract(multisigAddress, MinimumViableMultisig.abi, provider); | ||
let startingTotalAmountWithdrawn; | ||
try { | ||
startingTotalAmountWithdrawn = await multisig | ||
.functions | ||
.totalAmountWithdrawn(initialState.assetId); | ||
} | ||
catch (e) { | ||
const NOT_DEPLOYED_ERR = `contract not deployed (contractAddress="${multisigAddress}"`; | ||
if (!e.message.includes(NOT_DEPLOYED_ERR)) { | ||
throw new Error(e); | ||
} | ||
startingTotalAmountWithdrawn = Zero; | ||
} | ||
if (!initialState.startingTotalAmountWithdrawn.eq(startingTotalAmountWithdrawn)) { | ||
throw new Error(`Cannot install deposit app with invalid totalAmountWithdrawn. Expected ${startingTotalAmountWithdrawn}, got ${initialState.startingTotalAmountWithdrawn}`); | ||
} | ||
if (!initialState.startingMultisigBalance.eq(startingMultisigBalance)) { | ||
throw new Error(`Cannot install deposit app with invalid startingMultisigBalance. Expected ${startingMultisigBalance}, got ${initialState.startingMultisigBalance}`); | ||
} | ||
}; | ||
const uninstallDepositMiddleware = async (context, provider) => { | ||
const { role, appInstance, stateChannel, params, } = context; | ||
const latestState = appInstance.latestState; | ||
const currentMultisigBalance = latestState.assetId === CONVENTION_FOR_ETH_ASSET_ID | ||
? await provider.getBalance(stateChannel.multisigAddress) | ||
: await new Contract(latestState.assetId, ERC20.abi, provider) | ||
.functions | ||
.balanceOf(stateChannel.multisigAddress); | ||
if (currentMultisigBalance.lt(latestState.startingMultisigBalance)) { | ||
throw new Error(`Refusing to uninstall, current multisig balance (${currentMultisigBalance.toString()}) is less than starting multsig balance (${latestState.startingMultisigBalance.toString()})`); | ||
} | ||
if (role === ProtocolRoles.initiator | ||
&& latestState.transfers[0].to !== getSignerAddressFromPublicIdentifier(params.initiatorIdentifier)) { | ||
throw new Error(`Cannot uninstall deposit app without being the initiator`); | ||
} | ||
}; | ||
@@ -104,13 +152,14 @@ const HashLockTransferAppRegistryInfo = { | ||
}; | ||
const HASHLOCK_TRANSFER_STATE_TIMEOUT = Zero; | ||
const validateHashLockTransferApp = (params, blockNumber, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateHashLockTransferApp = (params, blockNumber, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -130,13 +179,14 @@ if (initialState.timelock.lt(blockNumber)) { | ||
}; | ||
const LINKED_TRANSFER_STATE_TIMEOUT = Zero; | ||
const validateSimpleLinkedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateSimpleLinkedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -156,13 +206,14 @@ unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
}; | ||
const SIGNED_TRANSFER_STATE_TIMEOUT = Zero; | ||
const validateSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateSignedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -178,6 +229,9 @@ unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
}; | ||
const SWAP_STATE_TIMEOUT = Zero; | ||
const ALLOWED_DISCREPANCY_PCT = 5; | ||
const validateSimpleSwapApp = (params, allowedSwaps, ourRate) => { | ||
const { responderDeposit, initiatorDeposit, initiatorDepositTokenAddress, responderDepositTokenAddress, } = params; | ||
const { responderDeposit, initiatorDeposit, initiatorDepositAssetId, responderDepositAssetId, } = params; | ||
const initiatorDepositTokenAddress = getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = getAddressFromAssetId(responderDepositAssetId); | ||
if (!allowedSwaps.find((swap) => swap.from === initiatorDepositTokenAddress && swap.to === responderDepositTokenAddress)) { | ||
@@ -203,8 +257,9 @@ throw new Error(`Swap from ${initiatorDepositTokenAddress} to ${responderDepositTokenAddress} is not valid. Valid swaps: ${stringify(allowedSwaps)}`); | ||
}; | ||
const WITHDRAW_STATE_TIMEOUT = Zero; | ||
const validateWithdrawApp = async (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateWithdrawApp = async (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = bigNumberifyJson(params.initialState); | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
@@ -219,4 +274,4 @@ const responderTransfer = initialState.transfers[1]; | ||
} | ||
if (initialState.signers[0] !== initiatorFreeBalanceAddress || | ||
initialState.signers[1] !== responderFreeBalanceAddress) { | ||
if (initialState.signers[0] !== initiatorSignerAddress || | ||
initialState.signers[1] !== responderSignerAddress) { | ||
throw new Error(`Cannot install a withdraw app if signers[] do not match multisig participant addresses. Signers[]: ${initialState.signers}`); | ||
@@ -227,3 +282,3 @@ } | ||
} | ||
let recovered = await recoverAddressWithEthers(initialState.data, initialState.signatures[0]); | ||
let recovered = await verifyChannelMessage(initialState.data, initialState.signatures[0]); | ||
if (recovered !== initialState.signers[0]) { | ||
@@ -235,48 +290,75 @@ throw new Error(`Cannot install withdraw app - incorrect signer recovered from initiator sig on data. | ||
class WithdrawETHCommitment extends MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value) { | ||
const iface = new Interface(ConditionalTransactionDelegateTarget.abi); | ||
class WithdrawCommitment extends MultisigCommitment { | ||
constructor(networkContext, multisigAddress, multisigOwners, recipient, assetId, amount, nonce) { | ||
super(multisigAddress, multisigOwners); | ||
this.networkContext = networkContext; | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.recipient = recipient; | ||
this.assetId = assetId; | ||
this.amount = amount; | ||
this.nonce = nonce; | ||
} | ||
getTransactionDetails() { | ||
return { | ||
to: this.to, | ||
value: bigNumberify(this.value), | ||
data: "0x", | ||
operation: MultisigOperation.Call, | ||
to: this.networkContext.ConditionalTransactionDelegateTarget, | ||
value: 0, | ||
data: iface.functions.withdrawWrapper.encode([ | ||
this.recipient, | ||
this.assetId, | ||
this.amount, | ||
this.nonce, | ||
]), | ||
operation: MultisigOperation.DelegateCall, | ||
}; | ||
} | ||
} | ||
class WithdrawERC20Commitment extends MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value, tokenAddress) { | ||
super(multisigAddress, multisigOwners); | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.tokenAddress = tokenAddress; | ||
const generateValidationMiddleware = async (contracts) => { | ||
if (!contracts.provider) { | ||
throw new Error(`Validation middleware needs access to a provider`); | ||
} | ||
getTransactionDetails() { | ||
return { | ||
data: new Interface(ERC20.abi).functions.transfer.encode([this.to, this.value]), | ||
operation: MultisigOperation.Call, | ||
to: this.tokenAddress, | ||
value: 0, | ||
}; | ||
const validationMiddleware = async (protocol, middlewareContext) => { | ||
switch (protocol) { | ||
case (ProtocolNames.setup): | ||
case (ProtocolNames.propose): | ||
case (ProtocolNames.install): | ||
case (ProtocolNames.update): | ||
case (ProtocolNames.takeAction): { | ||
break; | ||
} | ||
case (ProtocolNames.uninstall): { | ||
await uninstallMiddleware(contracts, middlewareContext); | ||
break; | ||
} | ||
default: | ||
throw new Error(`Unrecognized protocol name: ${protocol}`); | ||
} | ||
}; | ||
return validationMiddleware; | ||
}; | ||
const uninstallMiddleware = async (contracts, middlewareContext) => { | ||
const { appInstance } = middlewareContext; | ||
const appDef = appInstance.appInterface.addr; | ||
switch (appDef) { | ||
case (contracts.DepositApp): { | ||
await uninstallDepositMiddleware(middlewareContext, contracts.provider); | ||
break; | ||
} | ||
default: { | ||
return; | ||
} | ||
} | ||
} | ||
}; | ||
const AppRegistry = [ | ||
FastSignedTransferAppRegistryInfo, | ||
SimpleLinkedTransferAppRegistryInfo, | ||
SimpleSignedTransferAppRegistryInfo, | ||
SimpleTwoPartySwapAppRegistryInfo, | ||
CoinBalanceRefundAppRegistryInfo, | ||
WithdrawAppRegistryInfo, | ||
HashLockTransferAppRegistryInfo, | ||
DepositAppRegistryInfo, | ||
]; | ||
export { AppRegistry, CoinBalanceRefundAppRegistryInfo, FastSignedTransferAppRegistryInfo, HashLockTransferAppRegistryInfo, SimpleLinkedTransferAppRegistryInfo, SimpleSignedTransferAppRegistryInfo, SimpleTwoPartySwapAppRegistryInfo, SupportedApplications, WithdrawAppRegistryInfo, WithdrawERC20Commitment, WithdrawETHCommitment, baseCoinTransferValidation, commonAppProposalValidation, unidirectionalCoinTransferValidation, validateFastSignedTransferApp, validateHashLockTransferApp, validateSignedTransferApp, validateSimpleLinkedTransferApp, validateSimpleSwapApp, validateWithdrawApp }; | ||
export { AppRegistry, DEFAULT_APP_TIMEOUT, DEPOSIT_STATE_TIMEOUT, DepositAppRegistryInfo, HASHLOCK_TRANSFER_STATE_TIMEOUT, HashLockTransferAppRegistryInfo, LINKED_TRANSFER_STATE_TIMEOUT, SIGNED_TRANSFER_STATE_TIMEOUT, SWAP_STATE_TIMEOUT, SimpleLinkedTransferAppRegistryInfo, SimpleSignedTransferAppRegistryInfo, SimpleTwoPartySwapAppRegistryInfo, SupportedApplications, WITHDRAW_STATE_TIMEOUT, WithdrawAppRegistryInfo, WithdrawCommitment, baseCoinTransferValidation, commonAppProposalValidation, generateValidationMiddleware, unidirectionalCoinTransferValidation, uninstallDepositMiddleware, validateDepositApp, validateHashLockTransferApp, validateSignedTransferApp, validateSimpleLinkedTransferApp, validateSimpleSwapApp, validateWithdrawApp }; |
@@ -6,31 +6,18 @@ 'use strict'; | ||
var types = require('@connext/types'); | ||
var cfCore = require('@connext/cf-core'); | ||
var utils = require('@connext/utils'); | ||
var constants = require('ethers/constants'); | ||
var utils = require('ethers/utils'); | ||
var contracts = require('@connext/contracts'); | ||
var ethers = require('ethers'); | ||
var utils$1 = require('ethers/utils'); | ||
var cfCore = require('@connext/cf-core'); | ||
const CoinBalanceRefundAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: types.CoinBalanceRefundAppName, | ||
outcomeType: types.OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: types.CoinBalanceRefundAppStateEncoding, | ||
}; | ||
const FastSignedTransferAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: types.FastSignedTransferAppName, | ||
outcomeType: types.OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: types.FastSignedTransferAppStateEncoding, | ||
actionEncoding: types.FastSignedTransferAppActionEncoding, | ||
}; | ||
const SupportedApplications = types.enumify({ | ||
[types.CoinBalanceRefundAppName]: types.CoinBalanceRefundAppName, | ||
[types.SimpleLinkedTransferAppName]: types.SimpleLinkedTransferAppName, | ||
[types.SimpleSignedTransferAppName]: types.SimpleSignedTransferAppName, | ||
[types.SimpleTwoPartySwapAppName]: types.SimpleTwoPartySwapAppName, | ||
[types.FastSignedTransferAppName]: types.FastSignedTransferAppName, | ||
[types.WithdrawAppName]: types.WithdrawAppName, | ||
[types.HashLockTransferAppName]: types.HashLockTransferAppName, | ||
[types.DepositAppName]: types.DepositAppName, | ||
}); | ||
const DEFAULT_APP_TIMEOUT = utils.toBN(8640); | ||
@@ -40,3 +27,3 @@ const appProposalMatchesRegistry = (proposal, appRegistryInfo) => { | ||
proposal.abiEncodings.stateEncoding === appRegistryInfo.stateEncoding))) { | ||
throw new Error(`Proposed app details ${types.stringify(proposal)} do not match registry ${types.stringify(appRegistryInfo)}`); | ||
throw new Error(`Proposed app details ${utils.stringify(proposal)} do not match registry ${utils.stringify(appRegistryInfo)}`); | ||
} | ||
@@ -69,13 +56,16 @@ }; | ||
const commonAppProposalValidation = (params, appRegistryInfo, supportedTokenAddresses) => { | ||
const { initiatorDeposit, initiatorDepositTokenAddress, responderDeposit, responderDepositTokenAddress, } = params; | ||
const { initiatorDeposit, initiatorDepositAssetId, responderDeposit, responderDepositAssetId, } = params; | ||
appProposalMatchesRegistry(params, appRegistryInfo); | ||
const initiatorDepositTokenAddress = utils.getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = utils.getAddressFromAssetId(responderDepositAssetId); | ||
if (!supportedTokenAddresses.includes(initiatorDepositTokenAddress)) { | ||
throw new Error(`Unsupported "initiatorDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported initiatorDepositTokenAddress: ${initiatorDepositTokenAddress}`); | ||
} | ||
if (!supportedTokenAddresses.includes(responderDepositTokenAddress)) { | ||
throw new Error(`Unsupported "responderDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported responderDepositAssetId: ${responderDepositTokenAddress}`); | ||
} | ||
const isDeposit = appRegistryInfo.name === types.DepositAppName; | ||
if (responderDeposit.isZero() && | ||
initiatorDeposit.isZero() && | ||
appRegistryInfo.name !== types.CoinBalanceRefundAppName) { | ||
!isDeposit) { | ||
throw new Error(`Cannot install an app with zero valued deposits for both initiator and responder.`); | ||
@@ -85,18 +75,76 @@ } | ||
const validateFastSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const DepositAppRegistryInfo = { | ||
allowNodeInstall: true, | ||
name: types.DepositAppName, | ||
outcomeType: types.OutcomeType.SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER, | ||
stateEncoding: types.DepositAppStateEncoding, | ||
}; | ||
const DEPOSIT_STATE_TIMEOUT = DEFAULT_APP_TIMEOUT; | ||
const validateDepositApp = async (params, initiatorIdentifier, responderIdentifier, multisigAddress, provider) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
if (initialState.paymentId !== constants.HashZero) { | ||
throw new Error(`Cannot install with pre-populated paymentId`); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
const responderTransfer = initialState.transfers[1]; | ||
baseCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (initiatorSignerAddress !== initiatorTransfer.to) { | ||
throw new Error(`Cannot install deposit app with incorrect initiator transfer to address: Expected ${initiatorSignerAddress}, got ${initiatorTransfer.to}`); | ||
} | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
})[0]; | ||
unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (responderSignerAddress !== responderTransfer.to) { | ||
throw new Error(`Cannot install deposit app with incorrect responder transfer to address: Expected ${responderSignerAddress}, got ${responderTransfer.to}`); | ||
} | ||
if (!initialState.transfers[0].amount.isZero() || !initialState.transfers[1].amount.isZero()) { | ||
throw new Error(`Cannot install deposit app with nonzero initial balance: ${utils.stringify(initialState.transfers)}`); | ||
} | ||
if (initialState.multisigAddress !== multisigAddress) { | ||
throw new Error(`Cannot install deposit app with invalid multisig address. Expected ${multisigAddress}, got ${initialState.multisigAddress}`); | ||
} | ||
if (initialState.assetId !== utils.getAddressFromAssetId(params.initiatorDepositAssetId) | ||
|| initialState.assetId !== utils.getAddressFromAssetId(params.responderDepositAssetId)) { | ||
throw new Error(`Cannot install deposit app with invalid token address. Expected ${utils.getAddressFromAssetId(params.initiatorDepositAssetId)}, got ${initialState.assetId}`); | ||
} | ||
const startingMultisigBalance = initialState.assetId === types.CONVENTION_FOR_ETH_ASSET_ID | ||
? await provider.getBalance(multisigAddress) | ||
: await new ethers.Contract(initialState.assetId, contracts.ERC20.abi, provider) | ||
.functions | ||
.balanceOf(multisigAddress); | ||
const multisig = new ethers.Contract(multisigAddress, contracts.MinimumViableMultisig.abi, provider); | ||
let startingTotalAmountWithdrawn; | ||
try { | ||
startingTotalAmountWithdrawn = await multisig | ||
.functions | ||
.totalAmountWithdrawn(initialState.assetId); | ||
} | ||
catch (e) { | ||
const NOT_DEPLOYED_ERR = `contract not deployed (contractAddress="${multisigAddress}"`; | ||
if (!e.message.includes(NOT_DEPLOYED_ERR)) { | ||
throw new Error(e); | ||
} | ||
startingTotalAmountWithdrawn = constants.Zero; | ||
} | ||
if (!initialState.startingTotalAmountWithdrawn.eq(startingTotalAmountWithdrawn)) { | ||
throw new Error(`Cannot install deposit app with invalid totalAmountWithdrawn. Expected ${startingTotalAmountWithdrawn}, got ${initialState.startingTotalAmountWithdrawn}`); | ||
} | ||
if (!initialState.startingMultisigBalance.eq(startingMultisigBalance)) { | ||
throw new Error(`Cannot install deposit app with invalid startingMultisigBalance. Expected ${startingMultisigBalance}, got ${initialState.startingMultisigBalance}`); | ||
} | ||
}; | ||
const uninstallDepositMiddleware = async (context, provider) => { | ||
const { role, appInstance, stateChannel, params, } = context; | ||
const latestState = appInstance.latestState; | ||
const currentMultisigBalance = latestState.assetId === types.CONVENTION_FOR_ETH_ASSET_ID | ||
? await provider.getBalance(stateChannel.multisigAddress) | ||
: await new ethers.Contract(latestState.assetId, contracts.ERC20.abi, provider) | ||
.functions | ||
.balanceOf(stateChannel.multisigAddress); | ||
if (currentMultisigBalance.lt(latestState.startingMultisigBalance)) { | ||
throw new Error(`Refusing to uninstall, current multisig balance (${currentMultisigBalance.toString()}) is less than starting multsig balance (${latestState.startingMultisigBalance.toString()})`); | ||
} | ||
if (role === types.ProtocolRoles.initiator | ||
&& latestState.transfers[0].to !== utils.getSignerAddressFromPublicIdentifier(params.initiatorIdentifier)) { | ||
throw new Error(`Cannot uninstall deposit app without being the initiator`); | ||
} | ||
}; | ||
@@ -110,13 +158,14 @@ const HashLockTransferAppRegistryInfo = { | ||
}; | ||
const HASHLOCK_TRANSFER_STATE_TIMEOUT = constants.Zero; | ||
const validateHashLockTransferApp = (params, blockNumber, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateHashLockTransferApp = (params, blockNumber, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -136,17 +185,18 @@ if (initialState.timelock.lt(blockNumber)) { | ||
}; | ||
const LINKED_TRANSFER_STATE_TIMEOUT = constants.Zero; | ||
const validateSimpleLinkedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateSimpleLinkedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
if (!initialState.amount.eq(initiatorDeposit)) { | ||
throw new Error(`Payment amount bust be the same as initiator deposit ${types.stringify(params)}`); | ||
throw new Error(`Payment amount bust be the same as initiator deposit ${utils.stringify(params)}`); | ||
} | ||
@@ -162,13 +212,14 @@ }; | ||
}; | ||
const SIGNED_TRANSFER_STATE_TIMEOUT = constants.Zero; | ||
const validateSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateSignedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -184,13 +235,16 @@ unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); | ||
}; | ||
const SWAP_STATE_TIMEOUT = constants.Zero; | ||
const ALLOWED_DISCREPANCY_PCT = 5; | ||
const validateSimpleSwapApp = (params, allowedSwaps, ourRate) => { | ||
const { responderDeposit, initiatorDeposit, initiatorDepositTokenAddress, responderDepositTokenAddress, } = params; | ||
const { responderDeposit, initiatorDeposit, initiatorDepositAssetId, responderDepositAssetId, } = params; | ||
const initiatorDepositTokenAddress = utils.getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = utils.getAddressFromAssetId(responderDepositAssetId); | ||
if (!allowedSwaps.find((swap) => swap.from === initiatorDepositTokenAddress && swap.to === responderDepositTokenAddress)) { | ||
throw new Error(`Swap from ${initiatorDepositTokenAddress} to ${responderDepositTokenAddress} is not valid. Valid swaps: ${types.stringify(allowedSwaps)}`); | ||
throw new Error(`Swap from ${initiatorDepositTokenAddress} to ${responderDepositTokenAddress} is not valid. Valid swaps: ${utils.stringify(allowedSwaps)}`); | ||
} | ||
const calculated = types.calculateExchange(initiatorDeposit, ourRate); | ||
const calculated = utils.calculateExchange(initiatorDeposit, ourRate); | ||
const calculatedToActualDiscrepancy = calculated.sub(responderDeposit).abs(); | ||
const allowedDiscrepancy = calculated | ||
.mul(utils.bigNumberify(100).sub(ALLOWED_DISCREPANCY_PCT)) | ||
.mul(utils$1.bigNumberify(100).sub(ALLOWED_DISCREPANCY_PCT)) | ||
.div(100); | ||
@@ -209,8 +263,9 @@ if (calculatedToActualDiscrepancy.gt(allowedDiscrepancy)) { | ||
}; | ||
const WITHDRAW_STATE_TIMEOUT = constants.Zero; | ||
const validateWithdrawApp = async (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
const validateWithdrawApp = async (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = types.bigNumberifyJson(params.initialState); | ||
const initiatorFreeBalanceAddress = cfCore.xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = cfCore.xkeyKthAddress(responderPublicIdentifier); | ||
const initialState = utils.bigNumberifyJson(params.initialState); | ||
const initiatorSignerAddress = utils.getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = utils.getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
@@ -225,4 +280,4 @@ const responderTransfer = initialState.transfers[1]; | ||
} | ||
if (initialState.signers[0] !== initiatorFreeBalanceAddress || | ||
initialState.signers[1] !== responderFreeBalanceAddress) { | ||
if (initialState.signers[0] !== initiatorSignerAddress || | ||
initialState.signers[1] !== responderSignerAddress) { | ||
throw new Error(`Cannot install a withdraw app if signers[] do not match multisig participant addresses. Signers[]: ${initialState.signers}`); | ||
@@ -233,3 +288,3 @@ } | ||
} | ||
let recovered = await types.recoverAddressWithEthers(initialState.data, initialState.signatures[0]); | ||
let recovered = await utils.verifyChannelMessage(initialState.data, initialState.signatures[0]); | ||
if (recovered !== initialState.signers[0]) { | ||
@@ -241,52 +296,84 @@ throw new Error(`Cannot install withdraw app - incorrect signer recovered from initiator sig on data. | ||
class WithdrawETHCommitment extends cfCore.MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value) { | ||
const iface = new utils$1.Interface(contracts.ConditionalTransactionDelegateTarget.abi); | ||
class WithdrawCommitment extends cfCore.MultisigCommitment { | ||
constructor(networkContext, multisigAddress, multisigOwners, recipient, assetId, amount, nonce) { | ||
super(multisigAddress, multisigOwners); | ||
this.networkContext = networkContext; | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.recipient = recipient; | ||
this.assetId = assetId; | ||
this.amount = amount; | ||
this.nonce = nonce; | ||
} | ||
getTransactionDetails() { | ||
return { | ||
to: this.to, | ||
value: utils.bigNumberify(this.value), | ||
data: "0x", | ||
operation: types.MultisigOperation.Call, | ||
to: this.networkContext.ConditionalTransactionDelegateTarget, | ||
value: 0, | ||
data: iface.functions.withdrawWrapper.encode([ | ||
this.recipient, | ||
this.assetId, | ||
this.amount, | ||
this.nonce, | ||
]), | ||
operation: types.MultisigOperation.DelegateCall, | ||
}; | ||
} | ||
} | ||
class WithdrawERC20Commitment extends cfCore.MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value, tokenAddress) { | ||
super(multisigAddress, multisigOwners); | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.tokenAddress = tokenAddress; | ||
const generateValidationMiddleware = async (contracts) => { | ||
if (!contracts.provider) { | ||
throw new Error(`Validation middleware needs access to a provider`); | ||
} | ||
getTransactionDetails() { | ||
return { | ||
data: new utils.Interface(contracts.ERC20.abi).functions.transfer.encode([this.to, this.value]), | ||
operation: types.MultisigOperation.Call, | ||
to: this.tokenAddress, | ||
value: 0, | ||
}; | ||
const validationMiddleware = async (protocol, middlewareContext) => { | ||
switch (protocol) { | ||
case (types.ProtocolNames.setup): | ||
case (types.ProtocolNames.propose): | ||
case (types.ProtocolNames.install): | ||
case (types.ProtocolNames.update): | ||
case (types.ProtocolNames.takeAction): { | ||
break; | ||
} | ||
case (types.ProtocolNames.uninstall): { | ||
await uninstallMiddleware(contracts, middlewareContext); | ||
break; | ||
} | ||
default: | ||
throw new Error(`Unrecognized protocol name: ${protocol}`); | ||
} | ||
}; | ||
return validationMiddleware; | ||
}; | ||
const uninstallMiddleware = async (contracts, middlewareContext) => { | ||
const { appInstance } = middlewareContext; | ||
const appDef = appInstance.appInterface.addr; | ||
switch (appDef) { | ||
case (contracts.DepositApp): { | ||
await uninstallDepositMiddleware(middlewareContext, contracts.provider); | ||
break; | ||
} | ||
default: { | ||
return; | ||
} | ||
} | ||
} | ||
}; | ||
const AppRegistry = [ | ||
FastSignedTransferAppRegistryInfo, | ||
SimpleLinkedTransferAppRegistryInfo, | ||
SimpleSignedTransferAppRegistryInfo, | ||
SimpleTwoPartySwapAppRegistryInfo, | ||
CoinBalanceRefundAppRegistryInfo, | ||
WithdrawAppRegistryInfo, | ||
HashLockTransferAppRegistryInfo, | ||
DepositAppRegistryInfo, | ||
]; | ||
exports.AppRegistry = AppRegistry; | ||
exports.CoinBalanceRefundAppRegistryInfo = CoinBalanceRefundAppRegistryInfo; | ||
exports.FastSignedTransferAppRegistryInfo = FastSignedTransferAppRegistryInfo; | ||
exports.DEFAULT_APP_TIMEOUT = DEFAULT_APP_TIMEOUT; | ||
exports.DEPOSIT_STATE_TIMEOUT = DEPOSIT_STATE_TIMEOUT; | ||
exports.DepositAppRegistryInfo = DepositAppRegistryInfo; | ||
exports.HASHLOCK_TRANSFER_STATE_TIMEOUT = HASHLOCK_TRANSFER_STATE_TIMEOUT; | ||
exports.HashLockTransferAppRegistryInfo = HashLockTransferAppRegistryInfo; | ||
exports.LINKED_TRANSFER_STATE_TIMEOUT = LINKED_TRANSFER_STATE_TIMEOUT; | ||
exports.SIGNED_TRANSFER_STATE_TIMEOUT = SIGNED_TRANSFER_STATE_TIMEOUT; | ||
exports.SWAP_STATE_TIMEOUT = SWAP_STATE_TIMEOUT; | ||
exports.SimpleLinkedTransferAppRegistryInfo = SimpleLinkedTransferAppRegistryInfo; | ||
@@ -296,9 +383,11 @@ exports.SimpleSignedTransferAppRegistryInfo = SimpleSignedTransferAppRegistryInfo; | ||
exports.SupportedApplications = SupportedApplications; | ||
exports.WITHDRAW_STATE_TIMEOUT = WITHDRAW_STATE_TIMEOUT; | ||
exports.WithdrawAppRegistryInfo = WithdrawAppRegistryInfo; | ||
exports.WithdrawERC20Commitment = WithdrawERC20Commitment; | ||
exports.WithdrawETHCommitment = WithdrawETHCommitment; | ||
exports.WithdrawCommitment = WithdrawCommitment; | ||
exports.baseCoinTransferValidation = baseCoinTransferValidation; | ||
exports.commonAppProposalValidation = commonAppProposalValidation; | ||
exports.generateValidationMiddleware = generateValidationMiddleware; | ||
exports.unidirectionalCoinTransferValidation = unidirectionalCoinTransferValidation; | ||
exports.validateFastSignedTransferApp = validateFastSignedTransferApp; | ||
exports.uninstallDepositMiddleware = uninstallDepositMiddleware; | ||
exports.validateDepositApp = validateDepositApp; | ||
exports.validateHashLockTransferApp = validateHashLockTransferApp; | ||
@@ -305,0 +394,0 @@ exports.validateSignedTransferApp = validateSignedTransferApp; |
import { AppRegistryInfo } from "../shared"; | ||
export declare const HashLockTransferAppRegistryInfo: AppRegistryInfo; | ||
export declare const HASHLOCK_TRANSFER_STATE_TIMEOUT: import("ethers/utils").BigNumber; | ||
//# sourceMappingURL=registry.d.ts.map |
import { OutcomeType, HashLockTransferAppActionEncoding, HashLockTransferAppStateEncoding, HashLockTransferAppName, } from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
export const HashLockTransferAppRegistryInfo = { | ||
@@ -9,2 +10,3 @@ name: HashLockTransferAppName, | ||
}; | ||
export const HASHLOCK_TRANSFER_STATE_TIMEOUT = Zero; | ||
//# sourceMappingURL=registry.js.map |
export declare const validateHashLockTransferApp: (params: { | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
appDefinition: string; | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
defaultTimeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
initiatorDeposit: import("ethers/utils").BigNumber; | ||
initiatorDepositTokenAddress: string; | ||
initiatorDepositAssetId: string; | ||
meta?: Object | undefined; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
responderIdentifier: string; | ||
responderDeposit: import("ethers/utils").BigNumber; | ||
responderDepositTokenAddress: string; | ||
timeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
proposedToIdentifier: string; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
meta?: Object | undefined; | ||
}, blockNumber: number, initiatorPublicIdentifier: string, responderPublicIdentifier: string) => void; | ||
responderDepositAssetId: string; | ||
stateTimeout?: import("ethers/utils").BigNumber | undefined; | ||
}, blockNumber: number, initiatorIdentifier: string, responderIdentifier: string) => void; | ||
//# sourceMappingURL=validation.d.ts.map |
@@ -1,13 +0,13 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { getSignerAddressFromPublicIdentifier } from "@connext/utils"; | ||
import { unidirectionalCoinTransferValidation } from "../shared"; | ||
export const validateHashLockTransferApp = (params, blockNumber, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
export const validateHashLockTransferApp = (params, blockNumber, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -14,0 +14,0 @@ if (initialState.timelock.lt(blockNumber)) { |
import { AppRegistryType } from "./shared"; | ||
import { CoinBalanceRefundAppRegistryInfo } from "./CoinBalanceRefundApp"; | ||
import { FastSignedTransferAppRegistryInfo } from "./FastSignedTransferApp"; | ||
import { DepositAppRegistryInfo } from "./DepositApp"; | ||
import { SimpleLinkedTransferAppRegistryInfo } from "./SimpleLinkedTransferApp"; | ||
@@ -9,4 +8,2 @@ import { SimpleSignedTransferAppRegistryInfo } from "./SimpleSignedTransferApp"; | ||
export * from "./shared"; | ||
export * from "./CoinBalanceRefundApp"; | ||
export * from "./FastSignedTransferApp"; | ||
export * from "./HashLockTransferApp"; | ||
@@ -17,3 +14,5 @@ export * from "./SimpleLinkedTransferApp"; | ||
export * from "./WithdrawApp"; | ||
export { FastSignedTransferAppRegistryInfo, AppRegistryType, SimpleLinkedTransferAppRegistryInfo, SimpleSignedTransferAppRegistryInfo, SimpleTwoPartySwapAppRegistryInfo, CoinBalanceRefundAppRegistryInfo, }; | ||
export * from "./DepositApp"; | ||
export { AppRegistryType, SimpleLinkedTransferAppRegistryInfo, SimpleSignedTransferAppRegistryInfo, SimpleTwoPartySwapAppRegistryInfo, DepositAppRegistryInfo, }; | ||
export * from "./middleware"; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,3 +0,2 @@ | ||
import { CoinBalanceRefundAppRegistryInfo } from "./CoinBalanceRefundApp"; | ||
import { FastSignedTransferAppRegistryInfo } from "./FastSignedTransferApp"; | ||
import { DepositAppRegistryInfo } from "./DepositApp"; | ||
import { HashLockTransferAppRegistryInfo } from "./HashLockTransferApp"; | ||
@@ -9,13 +8,10 @@ import { SimpleLinkedTransferAppRegistryInfo } from "./SimpleLinkedTransferApp"; | ||
export const AppRegistry = [ | ||
FastSignedTransferAppRegistryInfo, | ||
SimpleLinkedTransferAppRegistryInfo, | ||
SimpleSignedTransferAppRegistryInfo, | ||
SimpleTwoPartySwapAppRegistryInfo, | ||
CoinBalanceRefundAppRegistryInfo, | ||
WithdrawAppRegistryInfo, | ||
HashLockTransferAppRegistryInfo, | ||
DepositAppRegistryInfo, | ||
]; | ||
export * from "./shared"; | ||
export * from "./CoinBalanceRefundApp"; | ||
export * from "./FastSignedTransferApp"; | ||
export * from "./HashLockTransferApp"; | ||
@@ -26,3 +22,5 @@ export * from "./SimpleLinkedTransferApp"; | ||
export * from "./WithdrawApp"; | ||
export { FastSignedTransferAppRegistryInfo, SimpleLinkedTransferAppRegistryInfo, SimpleSignedTransferAppRegistryInfo, SimpleTwoPartySwapAppRegistryInfo, CoinBalanceRefundAppRegistryInfo, }; | ||
export * from "./DepositApp"; | ||
export { SimpleLinkedTransferAppRegistryInfo, SimpleSignedTransferAppRegistryInfo, SimpleTwoPartySwapAppRegistryInfo, DepositAppRegistryInfo, }; | ||
export * from "./middleware"; | ||
//# sourceMappingURL=index.js.map |
@@ -1,10 +0,9 @@ | ||
import { CoinBalanceRefundAppName, FastSignedTransferAppName, HashLockTransferAppName, OutcomeType, SimpleLinkedTransferAppName, SimpleSignedTransferAppName, SimpleTwoPartySwapAppName, WithdrawAppName } from "@connext/types"; | ||
import { DepositAppName, HashLockTransferAppName, OutcomeType, SimpleLinkedTransferAppName, SimpleSignedTransferAppName, SimpleTwoPartySwapAppName, WithdrawAppName } from "@connext/types"; | ||
export declare const SupportedApplications: { | ||
[CoinBalanceRefundAppName]: "CoinBalanceRefundApp"; | ||
[SimpleLinkedTransferAppName]: "SimpleLinkedTransferApp"; | ||
[SimpleSignedTransferAppName]: "SimpleSignedTransferApp"; | ||
[SimpleTwoPartySwapAppName]: "SimpleTwoPartySwapApp"; | ||
[FastSignedTransferAppName]: "FastSignedTransferApp"; | ||
[WithdrawAppName]: "WithdrawApp"; | ||
[HashLockTransferAppName]: "HashLockTransferApp"; | ||
[DepositAppName]: "DepositApp"; | ||
}; | ||
@@ -20,2 +19,3 @@ export declare type SupportedApplications = (typeof SupportedApplications)[keyof typeof SupportedApplications]; | ||
export declare type AppRegistryType = AppRegistryInfo[]; | ||
export declare const DEFAULT_APP_TIMEOUT: import("ethers/utils").BigNumber; | ||
//# sourceMappingURL=registry.d.ts.map |
@@ -1,11 +0,12 @@ | ||
import { CoinBalanceRefundAppName, enumify, FastSignedTransferAppName, HashLockTransferAppName, SimpleLinkedTransferAppName, SimpleSignedTransferAppName, SimpleTwoPartySwapAppName, WithdrawAppName, } from "@connext/types"; | ||
import { DepositAppName, enumify, HashLockTransferAppName, SimpleLinkedTransferAppName, SimpleSignedTransferAppName, SimpleTwoPartySwapAppName, WithdrawAppName, } from "@connext/types"; | ||
import { toBN } from "@connext/utils"; | ||
export const SupportedApplications = enumify({ | ||
[CoinBalanceRefundAppName]: CoinBalanceRefundAppName, | ||
[SimpleLinkedTransferAppName]: SimpleLinkedTransferAppName, | ||
[SimpleSignedTransferAppName]: SimpleSignedTransferAppName, | ||
[SimpleTwoPartySwapAppName]: SimpleTwoPartySwapAppName, | ||
[FastSignedTransferAppName]: FastSignedTransferAppName, | ||
[WithdrawAppName]: WithdrawAppName, | ||
[HashLockTransferAppName]: HashLockTransferAppName, | ||
[DepositAppName]: DepositAppName, | ||
}); | ||
export const DEFAULT_APP_TIMEOUT = toBN(8640); | ||
//# sourceMappingURL=registry.js.map |
@@ -7,14 +7,15 @@ import { CoinTransfer } from "@connext/types"; | ||
export declare const commonAppProposalValidation: (params: { | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
appDefinition: string; | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
defaultTimeout: BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
initiatorDeposit: BigNumber; | ||
initiatorDepositTokenAddress: string; | ||
initiatorDepositAssetId: string; | ||
meta?: Object | undefined; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
responderIdentifier: string; | ||
responderDeposit: BigNumber; | ||
responderDepositTokenAddress: string; | ||
timeout: BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
proposedToIdentifier: string; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
meta?: Object | undefined; | ||
responderDepositAssetId: string; | ||
stateTimeout?: BigNumber | undefined; | ||
}, appRegistryInfo: AppRegistryInfo, supportedTokenAddresses: string[]) => void; | ||
//# sourceMappingURL=validation.d.ts.map |
@@ -1,2 +0,3 @@ | ||
import { CoinBalanceRefundAppName, stringify, } from "@connext/types"; | ||
import { DepositAppName, } from "@connext/types"; | ||
import { getAddressFromAssetId, stringify } from "@connext/utils"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -34,13 +35,16 @@ const appProposalMatchesRegistry = (proposal, appRegistryInfo) => { | ||
export const commonAppProposalValidation = (params, appRegistryInfo, supportedTokenAddresses) => { | ||
const { initiatorDeposit, initiatorDepositTokenAddress, responderDeposit, responderDepositTokenAddress, } = params; | ||
const { initiatorDeposit, initiatorDepositAssetId, responderDeposit, responderDepositAssetId, } = params; | ||
appProposalMatchesRegistry(params, appRegistryInfo); | ||
const initiatorDepositTokenAddress = getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = getAddressFromAssetId(responderDepositAssetId); | ||
if (!supportedTokenAddresses.includes(initiatorDepositTokenAddress)) { | ||
throw new Error(`Unsupported "initiatorDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported initiatorDepositTokenAddress: ${initiatorDepositTokenAddress}`); | ||
} | ||
if (!supportedTokenAddresses.includes(responderDepositTokenAddress)) { | ||
throw new Error(`Unsupported "responderDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported responderDepositAssetId: ${responderDepositTokenAddress}`); | ||
} | ||
const isDeposit = appRegistryInfo.name === DepositAppName; | ||
if (responderDeposit.isZero() && | ||
initiatorDeposit.isZero() && | ||
appRegistryInfo.name !== CoinBalanceRefundAppName) { | ||
!isDeposit) { | ||
throw new Error(`Cannot install an app with zero valued deposits for both initiator and responder.`); | ||
@@ -47,0 +51,0 @@ } |
import { AppRegistryInfo } from "../shared"; | ||
export declare const SimpleLinkedTransferAppRegistryInfo: AppRegistryInfo; | ||
export declare const LINKED_TRANSFER_STATE_TIMEOUT: import("ethers/utils").BigNumber; | ||
//# sourceMappingURL=registry.d.ts.map |
import { OutcomeType, SimpleLinkedTransferAppName, SimpleLinkedTransferAppActionEncoding, SimpleLinkedTransferAppStateEncoding, } from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
export const SimpleLinkedTransferAppRegistryInfo = { | ||
@@ -9,2 +10,3 @@ actionEncoding: SimpleLinkedTransferAppActionEncoding, | ||
}; | ||
export const LINKED_TRANSFER_STATE_TIMEOUT = Zero; | ||
//# sourceMappingURL=registry.js.map |
export declare const validateSimpleLinkedTransferApp: (params: { | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
appDefinition: string; | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
defaultTimeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
initiatorDeposit: import("ethers/utils").BigNumber; | ||
initiatorDepositTokenAddress: string; | ||
initiatorDepositAssetId: string; | ||
meta?: Object | undefined; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
responderIdentifier: string; | ||
responderDeposit: import("ethers/utils").BigNumber; | ||
responderDepositTokenAddress: string; | ||
timeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
proposedToIdentifier: string; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
meta?: Object | undefined; | ||
}, initiatorPublicIdentifier: string, responderPublicIdentifier: string) => void; | ||
responderDepositAssetId: string; | ||
stateTimeout?: import("ethers/utils").BigNumber | undefined; | ||
}, initiatorIdentifier: string, responderIdentifier: string) => void; | ||
//# sourceMappingURL=validation.d.ts.map |
@@ -1,14 +0,13 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { stringify, } from "@connext/types"; | ||
import { getSignerAddressFromPublicIdentifier, stringify } from "@connext/utils"; | ||
import { unidirectionalCoinTransferValidation } from "../shared"; | ||
export const validateSimpleLinkedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
export const validateSimpleLinkedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -15,0 +14,0 @@ unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); |
import { AppRegistryInfo } from "../shared"; | ||
export declare const SimpleSignedTransferAppRegistryInfo: AppRegistryInfo; | ||
export declare const SIGNED_TRANSFER_STATE_TIMEOUT: import("ethers/utils").BigNumber; | ||
//# sourceMappingURL=registry.d.ts.map |
import { OutcomeType, SimpleSignedTransferAppName, SimpleSignedTransferAppStateEncoding, SimpleSignedTransferAppActionEncoding, } from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
export const SimpleSignedTransferAppRegistryInfo = { | ||
@@ -9,2 +10,3 @@ allowNodeInstall: true, | ||
}; | ||
export const SIGNED_TRANSFER_STATE_TIMEOUT = Zero; | ||
//# sourceMappingURL=registry.js.map |
export declare const validateSignedTransferApp: (params: { | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
appDefinition: string; | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
defaultTimeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
initiatorDeposit: import("ethers/utils").BigNumber; | ||
initiatorDepositTokenAddress: string; | ||
initiatorDepositAssetId: string; | ||
meta?: Object | undefined; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
responderIdentifier: string; | ||
responderDeposit: import("ethers/utils").BigNumber; | ||
responderDepositTokenAddress: string; | ||
timeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
proposedToIdentifier: string; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
meta?: Object | undefined; | ||
}, initiatorPublicIdentifier: string, responderPublicIdentifier: string) => void; | ||
responderDepositAssetId: string; | ||
stateTimeout?: import("ethers/utils").BigNumber | undefined; | ||
}, initiatorIdentifier: string, responderIdentifier: string) => void; | ||
//# sourceMappingURL=validation.d.ts.map |
@@ -1,13 +0,13 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { getSignerAddressFromPublicIdentifier } from "@connext/utils"; | ||
import { unidirectionalCoinTransferValidation } from "../shared"; | ||
export const validateSignedTransferApp = (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
export const validateSignedTransferApp = (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = params.initialState; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -14,0 +14,0 @@ unidirectionalCoinTransferValidation(initiatorDeposit, responderDeposit, initiatorTransfer, responderTransfer); |
import { AppRegistryInfo } from "../shared"; | ||
export declare const SimpleTwoPartySwapAppRegistryInfo: AppRegistryInfo; | ||
export declare const SWAP_STATE_TIMEOUT: import("ethers/utils").BigNumber; | ||
//# sourceMappingURL=registry.d.ts.map |
import { OutcomeType, SimpleSwapAppStateEncoding, SimpleTwoPartySwapAppName, } from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
export const SimpleTwoPartySwapAppRegistryInfo = { | ||
@@ -8,2 +9,3 @@ allowNodeInstall: true, | ||
}; | ||
export const SWAP_STATE_TIMEOUT = Zero; | ||
//# sourceMappingURL=registry.js.map |
import { SwapRate } from "@connext/types"; | ||
export declare const validateSimpleSwapApp: (params: { | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
appDefinition: string; | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
defaultTimeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
initiatorDeposit: import("ethers/utils").BigNumber; | ||
initiatorDepositTokenAddress: string; | ||
initiatorDepositAssetId: string; | ||
meta?: Object | undefined; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
responderIdentifier: string; | ||
responderDeposit: import("ethers/utils").BigNumber; | ||
responderDepositTokenAddress: string; | ||
timeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
proposedToIdentifier: string; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
meta?: Object | undefined; | ||
responderDepositAssetId: string; | ||
stateTimeout?: import("ethers/utils").BigNumber | undefined; | ||
}, allowedSwaps: SwapRate[], ourRate: string) => void; | ||
//# sourceMappingURL=validation.d.ts.map |
@@ -1,6 +0,8 @@ | ||
import { calculateExchange, stringify, } from "@connext/types"; | ||
import { calculateExchange, getAddressFromAssetId, stringify } from "@connext/utils"; | ||
import { bigNumberify } from "ethers/utils"; | ||
const ALLOWED_DISCREPANCY_PCT = 5; | ||
export const validateSimpleSwapApp = (params, allowedSwaps, ourRate) => { | ||
const { responderDeposit, initiatorDeposit, initiatorDepositTokenAddress, responderDepositTokenAddress, } = params; | ||
const { responderDeposit, initiatorDeposit, initiatorDepositAssetId, responderDepositAssetId, } = params; | ||
const initiatorDepositTokenAddress = getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = getAddressFromAssetId(responderDepositAssetId); | ||
if (!allowedSwaps.find((swap) => swap.from === initiatorDepositTokenAddress && swap.to === responderDepositTokenAddress)) { | ||
@@ -7,0 +9,0 @@ throw new Error(`Swap from ${initiatorDepositTokenAddress} to ${responderDepositTokenAddress} is not valid. Valid swaps: ${stringify(allowedSwaps)}`); |
import { AppRegistryInfo } from "../shared"; | ||
export declare const WithdrawAppRegistryInfo: AppRegistryInfo; | ||
export declare const WITHDRAW_STATE_TIMEOUT: import("ethers/utils").BigNumber; | ||
//# sourceMappingURL=registry.d.ts.map |
import { OutcomeType, WithdrawAppStateEncoding, WithdrawAppActionEncoding, WithdrawAppName, } from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
export const WithdrawAppRegistryInfo = { | ||
@@ -9,2 +10,3 @@ allowNodeInstall: true, | ||
}; | ||
export const WITHDRAW_STATE_TIMEOUT = Zero; | ||
//# sourceMappingURL=registry.js.map |
export declare const validateWithdrawApp: (params: { | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
appDefinition: string; | ||
abiEncodings: import("@connext/types").AppABIEncodings; | ||
defaultTimeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
initiatorDeposit: import("ethers/utils").BigNumber; | ||
initiatorDepositTokenAddress: string; | ||
initiatorDepositAssetId: string; | ||
meta?: Object | undefined; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
responderIdentifier: string; | ||
responderDeposit: import("ethers/utils").BigNumber; | ||
responderDepositTokenAddress: string; | ||
timeout: import("ethers/utils").BigNumber; | ||
initialState: import("@connext/types").AppState; | ||
proposedToIdentifier: string; | ||
outcomeType: "TWO_PARTY_FIXED_OUTCOME" | "MULTI_ASSET_MULTI_PARTY_COIN_TRANSFER" | "SINGLE_ASSET_TWO_PARTY_COIN_TRANSFER"; | ||
meta?: Object | undefined; | ||
}, initiatorPublicIdentifier: string, responderPublicIdentifier: string) => Promise<void>; | ||
responderDepositAssetId: string; | ||
stateTimeout?: import("ethers/utils").BigNumber | undefined; | ||
}, initiatorIdentifier: string, responderIdentifier: string) => Promise<void>; | ||
//# sourceMappingURL=validation.d.ts.map |
@@ -1,10 +0,9 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { bigNumberifyJson, recoverAddressWithEthers, } from "@connext/types"; | ||
import { bigNumberifyJson, getSignerAddressFromPublicIdentifier, verifyChannelMessage } from "@connext/utils"; | ||
import { HashZero, Zero } from "ethers/constants"; | ||
import { unidirectionalCoinTransferValidation } from "../shared"; | ||
export const validateWithdrawApp = async (params, initiatorPublicIdentifier, responderPublicIdentifier) => { | ||
export const validateWithdrawApp = async (params, initiatorIdentifier, responderIdentifier) => { | ||
const { responderDeposit, initiatorDeposit } = params; | ||
const initialState = bigNumberifyJson(params.initialState); | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.transfers[0]; | ||
@@ -19,4 +18,4 @@ const responderTransfer = initialState.transfers[1]; | ||
} | ||
if (initialState.signers[0] !== initiatorFreeBalanceAddress || | ||
initialState.signers[1] !== responderFreeBalanceAddress) { | ||
if (initialState.signers[0] !== initiatorSignerAddress || | ||
initialState.signers[1] !== responderSignerAddress) { | ||
throw new Error(`Cannot install a withdraw app if signers[] do not match multisig participant addresses. Signers[]: ${initialState.signers}`); | ||
@@ -27,3 +26,3 @@ } | ||
} | ||
let recovered = await recoverAddressWithEthers(initialState.data, initialState.signatures[0]); | ||
let recovered = await verifyChannelMessage(initialState.data, initialState.signatures[0]); | ||
if (recovered !== initialState.signers[0]) { | ||
@@ -30,0 +29,0 @@ throw new Error(`Cannot install withdraw app - incorrect signer recovered from initiator sig on data. |
@@ -1,21 +0,15 @@ | ||
import { MultisigTransaction } from "@connext/types"; | ||
import { MultisigCommitment } from "@connext/cf-core"; | ||
import { MultisigTransaction, NetworkContext, ContractAddresses } from "@connext/types"; | ||
import { BigNumberish } from "ethers/utils"; | ||
export declare class WithdrawETHCommitment extends MultisigCommitment { | ||
export declare class WithdrawCommitment extends MultisigCommitment { | ||
readonly networkContext: NetworkContext | ContractAddresses; | ||
readonly multisigAddress: string; | ||
readonly multisigOwners: string[]; | ||
readonly to: string; | ||
readonly value: BigNumberish; | ||
constructor(multisigAddress: string, multisigOwners: string[], to: string, value: BigNumberish); | ||
readonly recipient: string; | ||
readonly assetId: string; | ||
readonly amount: BigNumberish; | ||
readonly nonce: string; | ||
constructor(networkContext: NetworkContext | ContractAddresses, multisigAddress: string, multisigOwners: string[], recipient: string, assetId: string, amount: BigNumberish, nonce: string); | ||
getTransactionDetails(): MultisigTransaction; | ||
} | ||
export declare class WithdrawERC20Commitment extends MultisigCommitment { | ||
readonly multisigAddress: string; | ||
readonly multisigOwners: string[]; | ||
readonly to: string; | ||
readonly value: BigNumberish; | ||
readonly tokenAddress: string; | ||
constructor(multisigAddress: string, multisigOwners: string[], to: string, value: BigNumberish, tokenAddress: string); | ||
getTransactionDetails(): MultisigTransaction; | ||
} | ||
//# sourceMappingURL=withdrawCommitment.d.ts.map |
@@ -0,37 +1,28 @@ | ||
import { MultisigCommitment } from "@connext/cf-core"; | ||
import { ConditionalTransactionDelegateTarget } from "@connext/contracts"; | ||
import { MultisigOperation } from "@connext/types"; | ||
import { MultisigCommitment } from "@connext/cf-core"; | ||
import { ERC20 } from "@connext/contracts"; | ||
import { bigNumberify, Interface } from "ethers/utils"; | ||
export class WithdrawETHCommitment extends MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value) { | ||
import { Interface } from "ethers/utils"; | ||
const iface = new Interface(ConditionalTransactionDelegateTarget.abi); | ||
export class WithdrawCommitment extends MultisigCommitment { | ||
constructor(networkContext, multisigAddress, multisigOwners, recipient, assetId, amount, nonce) { | ||
super(multisigAddress, multisigOwners); | ||
this.networkContext = networkContext; | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.recipient = recipient; | ||
this.assetId = assetId; | ||
this.amount = amount; | ||
this.nonce = nonce; | ||
} | ||
getTransactionDetails() { | ||
return { | ||
to: this.to, | ||
value: bigNumberify(this.value), | ||
data: "0x", | ||
operation: MultisigOperation.Call, | ||
}; | ||
} | ||
} | ||
export class WithdrawERC20Commitment extends MultisigCommitment { | ||
constructor(multisigAddress, multisigOwners, to, value, tokenAddress) { | ||
super(multisigAddress, multisigOwners); | ||
this.multisigAddress = multisigAddress; | ||
this.multisigOwners = multisigOwners; | ||
this.to = to; | ||
this.value = value; | ||
this.tokenAddress = tokenAddress; | ||
} | ||
getTransactionDetails() { | ||
return { | ||
data: new Interface(ERC20.abi).functions.transfer.encode([this.to, this.value]), | ||
operation: MultisigOperation.Call, | ||
to: this.tokenAddress, | ||
to: this.networkContext.ConditionalTransactionDelegateTarget, | ||
value: 0, | ||
data: iface.functions.withdrawWrapper.encode([ | ||
this.recipient, | ||
this.assetId, | ||
this.amount, | ||
this.nonce, | ||
]), | ||
operation: MultisigOperation.DelegateCall, | ||
}; | ||
@@ -38,0 +29,0 @@ } |
{ | ||
"name": "@connext/apps", | ||
"version": "6.0.0-alpha3", | ||
"version": "6.0.1", | ||
"description": "Connext Counterfactual Apps", | ||
@@ -21,6 +21,6 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@connext/cf-core": "6.0.0-alpha.2", | ||
"@connext/contracts": "1.0.5", | ||
"@connext/crypto": "6.0.0-alpha.2", | ||
"@connext/types": "6.0.0-alpha3", | ||
"@connext/cf-core": "6.0.1", | ||
"@connext/contracts": "2.0.2", | ||
"@connext/utils": "6.0.1", | ||
"@connext/types": "6.0.1", | ||
"ethers": "4.0.46", | ||
@@ -27,0 +27,0 @@ "rollup": "1.31.1", |
@@ -7,2 +7,3 @@ import { | ||
} from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -18,1 +19,4 @@ import { AppRegistryInfo } from "../shared"; | ||
}; | ||
// timeout default values | ||
export const HASHLOCK_TRANSFER_STATE_TIMEOUT = Zero; |
@@ -1,3 +0,3 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { MethodParams, CoinTransfer, HashLockTransferAppState } from "@connext/types"; | ||
import { getSignerAddressFromPublicIdentifier } from "@connext/utils"; | ||
@@ -9,4 +9,4 @@ import { unidirectionalCoinTransferValidation } from "../shared"; | ||
blockNumber: number, | ||
initiatorPublicIdentifier: string, | ||
responderPublicIdentifier: string, | ||
initiatorIdentifier: string, | ||
responderIdentifier: string, | ||
) => { | ||
@@ -16,10 +16,10 @@ const { responderDeposit, initiatorDeposit } = params; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer: CoinTransfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer: CoinTransfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -26,0 +26,0 @@ |
import { AppRegistryType } from "./shared"; | ||
import { CoinBalanceRefundAppRegistryInfo } from "./CoinBalanceRefundApp"; | ||
import { FastSignedTransferAppRegistryInfo } from "./FastSignedTransferApp"; | ||
import { DepositAppRegistryInfo } from "./DepositApp"; | ||
import { HashLockTransferAppRegistryInfo } from "./HashLockTransferApp"; | ||
@@ -11,14 +10,11 @@ import { SimpleLinkedTransferAppRegistryInfo } from "./SimpleLinkedTransferApp"; | ||
export const AppRegistry: AppRegistryType = [ | ||
FastSignedTransferAppRegistryInfo, | ||
SimpleLinkedTransferAppRegistryInfo, | ||
SimpleSignedTransferAppRegistryInfo, | ||
SimpleTwoPartySwapAppRegistryInfo, | ||
CoinBalanceRefundAppRegistryInfo, | ||
WithdrawAppRegistryInfo, | ||
HashLockTransferAppRegistryInfo, | ||
DepositAppRegistryInfo, | ||
]; | ||
export * from "./shared"; | ||
export * from "./CoinBalanceRefundApp"; | ||
export * from "./FastSignedTransferApp"; | ||
export * from "./HashLockTransferApp"; | ||
@@ -29,5 +25,5 @@ export * from "./SimpleLinkedTransferApp"; | ||
export * from "./WithdrawApp"; | ||
export * from "./DepositApp"; | ||
export { | ||
FastSignedTransferAppRegistryInfo, | ||
AppRegistryType, | ||
@@ -37,3 +33,5 @@ SimpleLinkedTransferAppRegistryInfo, | ||
SimpleTwoPartySwapAppRegistryInfo, | ||
CoinBalanceRefundAppRegistryInfo, | ||
DepositAppRegistryInfo, | ||
}; | ||
export * from "./middleware"; |
import { | ||
CoinBalanceRefundAppName, | ||
DepositAppName, | ||
enumify, | ||
FastSignedTransferAppName, | ||
HashLockTransferAppName, | ||
@@ -12,11 +11,11 @@ OutcomeType, | ||
} from "@connext/types"; | ||
import { toBN } from "@connext/utils"; | ||
export const SupportedApplications = enumify({ | ||
[CoinBalanceRefundAppName]: CoinBalanceRefundAppName, | ||
[SimpleLinkedTransferAppName]: SimpleLinkedTransferAppName, | ||
[SimpleSignedTransferAppName]: SimpleSignedTransferAppName, | ||
[SimpleTwoPartySwapAppName]: SimpleTwoPartySwapAppName, | ||
[FastSignedTransferAppName]: FastSignedTransferAppName, | ||
[WithdrawAppName]: WithdrawAppName, | ||
[HashLockTransferAppName]: HashLockTransferAppName, | ||
[DepositAppName]: DepositAppName, | ||
}); | ||
@@ -36,1 +35,4 @@ | ||
export type AppRegistryType = AppRegistryInfo[]; | ||
// timeout default values | ||
export const DEFAULT_APP_TIMEOUT = toBN(8640); // 6 blocks per min (ethereum) * 60 mins * 24h |
import { | ||
CoinBalanceRefundAppName, | ||
CoinTransfer, | ||
MethodParams, | ||
stringify, | ||
DepositAppName, | ||
} from "@connext/types"; | ||
import { getAddressFromAssetId, stringify } from "@connext/utils"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -39,4 +39,4 @@ import { BigNumber } from "ethers/utils"; | ||
* @param params | ||
* @param initiatorPublicIdentifier | ||
* @param responderPublicIdentifier | ||
* @param initiatorIdentifier | ||
* @param responderIdentifier | ||
*/ | ||
@@ -70,4 +70,4 @@ export const baseCoinTransferValidation = ( | ||
* @param params | ||
* @param initiatorPublicIdentifier | ||
* @param responderPublicIdentifier | ||
* @param initiatorIdentifier | ||
* @param responderIdentifier | ||
*/ | ||
@@ -118,5 +118,5 @@ export const unidirectionalCoinTransferValidation = ( | ||
initiatorDeposit, | ||
initiatorDepositTokenAddress, | ||
initiatorDepositAssetId, | ||
responderDeposit, | ||
responderDepositTokenAddress, | ||
responderDepositAssetId, | ||
} = params; | ||
@@ -126,8 +126,13 @@ | ||
const initiatorDepositTokenAddress = | ||
getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = | ||
getAddressFromAssetId(responderDepositAssetId); | ||
if (!supportedTokenAddresses.includes(initiatorDepositTokenAddress)) { | ||
throw new Error(`Unsupported "initiatorDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported initiatorDepositTokenAddress: ${initiatorDepositTokenAddress}`); | ||
} | ||
if (!supportedTokenAddresses.includes(responderDepositTokenAddress)) { | ||
throw new Error(`Unsupported "responderDepositTokenAddress" provided`); | ||
throw new Error(`Unsupported responderDepositAssetId: ${responderDepositTokenAddress}`); | ||
} | ||
@@ -137,6 +142,7 @@ | ||
// with games | ||
const isDeposit = appRegistryInfo.name === DepositAppName; | ||
if ( | ||
responderDeposit.isZero() && | ||
initiatorDeposit.isZero() && | ||
appRegistryInfo.name !== CoinBalanceRefundAppName | ||
!isDeposit | ||
) { | ||
@@ -143,0 +149,0 @@ throw new Error( |
@@ -7,2 +7,3 @@ import { | ||
} from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -19,1 +20,3 @@ import { AppRegistryInfo } from "../shared"; | ||
// timeout default values | ||
export const LINKED_TRANSFER_STATE_TIMEOUT = Zero; |
@@ -1,2 +0,1 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { | ||
@@ -6,4 +5,4 @@ MethodParams, | ||
SimpleLinkedTransferAppState, | ||
stringify, | ||
} from "@connext/types"; | ||
import { getSignerAddressFromPublicIdentifier, stringify } from "@connext/utils"; | ||
@@ -14,4 +13,4 @@ import { unidirectionalCoinTransferValidation } from "../shared"; | ||
params: MethodParams.ProposeInstall, | ||
initiatorPublicIdentifier: string, | ||
responderPublicIdentifier: string, | ||
initiatorIdentifier: string, | ||
responderIdentifier: string, | ||
) => { | ||
@@ -21,10 +20,10 @@ const { responderDeposit, initiatorDeposit } = params; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer: CoinTransfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
const responderTransfer = initialState.coinTransfers.filter((transfer: CoinTransfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -31,0 +30,0 @@ |
@@ -7,2 +7,3 @@ import { | ||
} from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -18,1 +19,4 @@ import { AppRegistryInfo } from "../shared"; | ||
}; | ||
// timeout default values | ||
export const SIGNED_TRANSFER_STATE_TIMEOUT = Zero; |
@@ -1,2 +0,1 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { | ||
@@ -7,2 +6,3 @@ MethodParams, | ||
} from "@connext/types"; | ||
import { getSignerAddressFromPublicIdentifier } from "@connext/utils"; | ||
@@ -13,4 +13,4 @@ import { unidirectionalCoinTransferValidation } from "../shared"; | ||
params: MethodParams.ProposeInstall, | ||
initiatorPublicIdentifier: string, | ||
responderPublicIdentifier: string, | ||
initiatorIdentifier: string, | ||
responderIdentifier: string, | ||
) => { | ||
@@ -20,8 +20,8 @@ const { responderDeposit, initiatorDeposit } = params; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
// initiator is sender | ||
const initiatorTransfer = initialState.coinTransfers.filter((transfer: CoinTransfer) => { | ||
return transfer.to === initiatorFreeBalanceAddress; | ||
return transfer.to === initiatorSignerAddress; | ||
})[0]; | ||
@@ -31,3 +31,3 @@ | ||
const responderTransfer = initialState.coinTransfers.filter((transfer: CoinTransfer) => { | ||
return transfer.to === responderFreeBalanceAddress; | ||
return transfer.to === responderSignerAddress; | ||
})[0]; | ||
@@ -34,0 +34,0 @@ |
@@ -6,2 +6,3 @@ import { | ||
} from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -16,1 +17,4 @@ import { AppRegistryInfo } from "../shared"; | ||
}; | ||
// timeout default values | ||
export const SWAP_STATE_TIMEOUT = Zero; |
import { | ||
MethodParams, | ||
AllowedSwap, | ||
calculateExchange, | ||
stringify, | ||
SwapRate, | ||
} from "@connext/types"; | ||
import { calculateExchange, getAddressFromAssetId, stringify } from "@connext/utils"; | ||
import { bigNumberify } from "ethers/utils"; | ||
@@ -20,6 +19,11 @@ | ||
initiatorDeposit, | ||
initiatorDepositTokenAddress, | ||
responderDepositTokenAddress, | ||
initiatorDepositAssetId, | ||
responderDepositAssetId, | ||
} = params; | ||
const initiatorDepositTokenAddress = | ||
getAddressFromAssetId(initiatorDepositAssetId); | ||
const responderDepositTokenAddress = | ||
getAddressFromAssetId(responderDepositAssetId); | ||
if ( | ||
@@ -26,0 +30,0 @@ !allowedSwaps.find( |
@@ -7,2 +7,3 @@ import { | ||
} from "@connext/types"; | ||
import { Zero } from "ethers/constants"; | ||
@@ -18,1 +19,4 @@ import { AppRegistryInfo } from "../shared"; | ||
}; | ||
// timeout default values | ||
export const WITHDRAW_STATE_TIMEOUT = Zero; |
@@ -1,8 +0,3 @@ | ||
import { xkeyKthAddress } from "@connext/cf-core"; | ||
import { | ||
bigNumberifyJson, | ||
MethodParams, | ||
recoverAddressWithEthers, | ||
WithdrawAppState, | ||
} from "@connext/types"; | ||
import { MethodParams, WithdrawAppState } from "@connext/types"; | ||
import { bigNumberifyJson, getSignerAddressFromPublicIdentifier, verifyChannelMessage } from "@connext/utils"; | ||
import { HashZero, Zero } from "ethers/constants"; | ||
@@ -14,4 +9,4 @@ | ||
params: MethodParams.ProposeInstall, | ||
initiatorPublicIdentifier: string, | ||
responderPublicIdentifier: string, | ||
initiatorIdentifier: string, | ||
responderIdentifier: string, | ||
) => { | ||
@@ -21,4 +16,4 @@ const { responderDeposit, initiatorDeposit } = params; | ||
const initiatorFreeBalanceAddress = xkeyKthAddress(initiatorPublicIdentifier); | ||
const responderFreeBalanceAddress = xkeyKthAddress(responderPublicIdentifier); | ||
const initiatorSignerAddress = getSignerAddressFromPublicIdentifier(initiatorIdentifier); | ||
const responderSignerAddress = getSignerAddressFromPublicIdentifier(responderIdentifier); | ||
@@ -46,4 +41,4 @@ const initiatorTransfer = initialState.transfers[0]; | ||
if ( | ||
initialState.signers[0] !== initiatorFreeBalanceAddress || | ||
initialState.signers[1] !== responderFreeBalanceAddress | ||
initialState.signers[0] !== initiatorSignerAddress || | ||
initialState.signers[1] !== responderSignerAddress | ||
) { | ||
@@ -61,3 +56,3 @@ throw new Error( | ||
let recovered = await recoverAddressWithEthers(initialState.data, initialState.signatures[0]); | ||
let recovered = await verifyChannelMessage(initialState.data, initialState.signatures[0]); | ||
@@ -64,0 +59,0 @@ if (recovered !== initialState.signers[0]) { |
@@ -1,12 +0,16 @@ | ||
import { MultisigTransaction, MultisigOperation } from "@connext/types"; | ||
import { MultisigCommitment } from "@connext/cf-core"; | ||
import { ERC20 } from "@connext/contracts"; | ||
import { BigNumberish, bigNumberify, Interface } from "ethers/utils"; | ||
import { ConditionalTransactionDelegateTarget } from "@connext/contracts"; | ||
import { MultisigTransaction, MultisigOperation, NetworkContext, ContractAddresses } from "@connext/types"; | ||
import { BigNumberish, Interface } from "ethers/utils"; | ||
export class WithdrawETHCommitment extends MultisigCommitment { | ||
const iface = new Interface(ConditionalTransactionDelegateTarget.abi); | ||
export class WithdrawCommitment extends MultisigCommitment { | ||
public constructor( | ||
public readonly networkContext: NetworkContext | ContractAddresses, | ||
public readonly multisigAddress: string, | ||
public readonly multisigOwners: string[], | ||
public readonly to: string, | ||
public readonly value: BigNumberish, | ||
public readonly recipient: string, | ||
public readonly assetId: string, | ||
public readonly amount: BigNumberish, | ||
public readonly nonce: string, | ||
) { | ||
@@ -18,29 +22,13 @@ super(multisigAddress, multisigOwners); | ||
return { | ||
to: this.to, | ||
value: bigNumberify(this.value), | ||
data: "0x", | ||
operation: MultisigOperation.Call, | ||
}; | ||
} | ||
} | ||
export class WithdrawERC20Commitment extends MultisigCommitment { | ||
public constructor( | ||
public readonly multisigAddress: string, | ||
public readonly multisigOwners: string[], | ||
public readonly to: string, | ||
public readonly value: BigNumberish, | ||
public readonly tokenAddress: string, | ||
) { | ||
super(multisigAddress, multisigOwners); | ||
} | ||
public getTransactionDetails(): MultisigTransaction { | ||
return { | ||
data: new Interface(ERC20.abi).functions.transfer.encode([this.to, this.value]), | ||
operation: MultisigOperation.Call, | ||
to: this.tokenAddress, | ||
to: this.networkContext.ConditionalTransactionDelegateTarget, | ||
value: 0, | ||
data: iface.functions.withdrawWrapper.encode([ | ||
this.recipient, | ||
this.assetId, | ||
this.amount, | ||
this.nonce, | ||
]), | ||
operation: MultisigOperation.DelegateCall, | ||
}; | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
529335
2343
2
0
125