@moveflow/sui-sdk.js
Version:
Typescript SDK for MoveFlow on SUI blockchain
1,356 lines (1,211 loc) • 49.4 kB
text/typescript
import {
Ed25519Keypair,
RawSigner,
JsonRpcProvider,
Connection,
} from '@mysten/sui.js'
import { Network, getConfig } from './config'
import { Stream, StreamDirection, StreamCreationResult } from './stream'
describe('Stream', () => {
const conn = new Connection({ fullnode: getConfig(Network.testnet).fullNodeUrl })
const rpcProvider = new JsonRpcProvider(conn)
const path = 'm/44\'/784\'/0\'/0\'/0\''
// admin address 0x914145bfea385c09095123891f3cbfc36ab98e0ab88fbb985c92319399ddf92e
const adminMnemonic = 'member gate bicycle bicycle give lobster engine film mango pave critic chat'
const adminKeypair = Ed25519Keypair.deriveKeypair(adminMnemonic, path)
const admin = new RawSigner(adminKeypair, rpcProvider)
// sender address 0x7905ae3ed4a5a77284684fa86fd83c38a9f138b0cc390721c46bca3aaafaf26c
const senderMnemonic = 'indoor educate spin hour trick faculty indoor grid aware cliff jungle raccoon'
const senderKeypair = Ed25519Keypair.deriveKeypair(senderMnemonic, path)
const sender = new RawSigner(senderKeypair, rpcProvider)
// recipient address 0x45f5a96940e84dd876b1adc2c434961178fc94cb79c23a9f8ddc57c996255869
const recipientMnemonic = 'evidence paddle silver glance tackle stage solution enlist input canoe say chest'
const recipientKeypair = Ed25519Keypair.deriveKeypair(recipientMnemonic, path)
const recipient = new RawSigner(recipientKeypair, rpcProvider)
// another recipient address 0x08bb80f552385ab82fa689ba24b157ec14860aff6dde76a5cbca00d8e59ad1a3
const anotherRecipientMnemonic = 'because artist ketchup acoustic merge illness math glide echo coin roast have'
const anotherRecipientKeypair = Ed25519Keypair.deriveKeypair(anotherRecipientMnemonic, path)
const anotherRecipient = new RawSigner(anotherRecipientKeypair, rpcProvider)
const stream = new Stream(Network.testnet)
let streamCreationResult: StreamCreationResult = {
streamId: '',
senderCap: '',
recipientCap: '',
}
const coinTypes = [
'0x2::sui::SUI',
'0x467c38a912a5927b73d1d8f821d30f9c8ad8d87e5228869a79866668938a8b9c::paper_coin::PAPER_COIN',
'xyz::paper_coin::PAPER_COIN',
'0x467c38a912a5927b73d1d8f821d30f9c8ad8d87e5228869a79866668938a8b9c::paper_coin',
]
test('constructor works', () => {
expect(stream.network).toBe(Network.testnet)
expect(stream.networkName).toBe('testnet')
})
// --- createTransaction ---
test('createTransaction works', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(10000000)
const startTime = Math.floor(Date.now() / 1000) - 10
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = 1 // 1 second
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
const txb = await stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)
txb.setSender(senderAddress)
const txBytes = await txb.build({ provider: rpcProvider })
const response = await sender.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
streamCreationResult = stream.getStreamCreationResult(response as any)
console.log('--- streamCreationResult ---')
console.log(streamCreationResult)
})
test('createTransaction should throw error if name is too long', async () => {
const name = 'first'.repeat(210)
const remark = 'first sui stream'
const depositAmount = BigInt(100000)
const startTime = Math.floor(Date.now() / 1000) - 10
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = 1 // 1 second
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
'name exceeds the maximum length 1024 characters'
)
})
test('createTransaction should throw error if remark is too long', async () => {
const name = 'first'
const remark = 'first sui stream'.repeat(70)
const depositAmount = BigInt(100000)
const startTime = Math.floor(Date.now() / 1000) - 10
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = 1 // 1 second
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
'remark exceeds the maximum length 1024 characters'
)
})
// test('createTransaction should throw error if sender address is invalid', async () => {
// const name = 'first'
// const remark = 'first sui stream'
// const depositAmount = BigInt(100000)
// const startTime = Math.floor(Date.now() / 1000) - 10
// const duration = 24 * 60 * 60 // 1 day
// const stopTime = startTime + duration
// const interval = 1 // 1 second
// const senderAddress = 'a-bc_xy'
// const recipientAddress = await recipient.getAddress()
// await expect(stream.createTransaction(
// coinTypes[0],
// name,
// remark,
// senderAddress,
// recipientAddress,
// depositAmount,
// startTime,
// stopTime,
// interval
// )).rejects.toThrowError('Invalid Sui address')
// })
// test('createTransaction should throw error if recipient address is invalid', async () => {
// const name = 'first'
// const remark = 'first sui stream'
// const depositAmount = BigInt(100000)
// const startTime = Math.floor(Date.now() / 1000) - 10
// const duration = 24 * 60 * 60 // 1 day
// const stopTime = startTime + duration
// const interval = 1 // 1 second
// const senderAddress = await sender.getAddress()
// const recipientAddress = '02456*'
// await expect(stream.createTransaction(
// coinTypes[0],
// name,
// remark,
// senderAddress,
// recipientAddress,
// depositAmount,
// startTime,
// stopTime,
// interval
// )).rejects.toThrowError('Invalid Sui address')
// })
test('createTransaction should throw error if stopTime is earlier than startTime', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(100000)
const startTime = Math.floor(Date.now() / 1000) - 10
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime - duration
const interval = 1 // 1 second
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
`stopTime ${stopTime} is before startTime ${startTime}`
)
})
test('createTransaction should throw error if stopTime is in the past', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(100000)
const startTime = Math.floor(Date.now() / 1000) - 100
const stopTime = Math.floor(Date.now() / 1000) - 10
const interval = 1 // 1 second
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
`stopTime ${stopTime} is in the past`
)
})
test('createTransaction should throw error if depositAmount is too large', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(10 ** 20)
const startTime = Math.floor(Date.now() / 1000) - 10
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = 1 // 1 second
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
`the sender ${senderAddress} has not enough balance of ${coinTypes[0]} to pay the deposit ${depositAmount}`
)
})
test('createTransaction should throw error if time is negative', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(10 ** 20)
const startTime = Math.floor(Date.now() / 1000) - 10
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = -1
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
`The number ${interval} is negative or not an integer`
)
})
test('createTransaction should throw error if time is not an integer', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(10 ** 20)
const startTime = Math.floor(Date.now() / 1000) - 9.9
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = 1
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
`The number ${startTime} is negative or not an integer`
)
})
test('createTransaction should throw error if depositAmount is negative', async () => {
const name = 'first'
const remark = 'first sui stream'
const depositAmount = BigInt(-1)
const startTime = Math.floor(Date.now() / 1000) - 9.9
const duration = 24 * 60 * 60 // 1 day
const stopTime = startTime + duration
const interval = 1
const senderAddress = await sender.getAddress()
const recipientAddress = await recipient.getAddress()
await expect(stream.createTransaction(
coinTypes[0],
name,
remark,
senderAddress,
recipientAddress,
depositAmount,
startTime,
stopTime,
interval
)).rejects.toThrowError(
`depositAmount ${depositAmount} is negative`
)
})
// --- getStreamById ---
test('getStreamById works', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
expect(streamInfo.id).toBe(streamCreationResult.streamId)
})
// test('getStreamById throws error if streamId is invalid', async () => {
// const streamId = streamCreationResult.streamId + 'b'
// await expect(stream.getStreamById(streamId)).rejects.toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// --- extendTransaction ---
test('extendTransaction works', async () => {
const duration = 24 * 60 * 60 // 1 day
const stopTime = Math.floor(Date.now() / 1000) + duration * 2
const senderAddress = await sender.getAddress()
const txb = await stream.extendTransaction(
coinTypes[0],
senderAddress,
streamCreationResult.senderCap,
streamCreationResult.streamId,
stopTime
)
txb.setSender(senderAddress)
txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
const txBytes = await txb.build({ provider: rpcProvider })
const response = await sender.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
console.log('--- extendTransaction Response ---')
console.log(response)
})
// test('extendTransaction should throw error if sender is not a valid address', async () => {
// const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
// const newStopTime = streamInfo.stopTime + 10
// const senderAddress = 'abcdefg'
// await expect(stream.extendTransaction(
// coinTypes[0],
// senderAddress,
// streamCreationResult.senderCap,
// streamCreationResult.streamId,
// newStopTime
// )).rejects.toThrowError('Invalid Sui address'
// )
// })
// test('extendTransaction should throw error if senderCap is not a valid object', async () => {
// const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
// const newStopTime = streamInfo.stopTime + 10
// const senderAddress = await sender.getAddress()
// const senderCap = streamCreationResult.senderCap + '123xyz'
// await expect(stream.extendTransaction(
// coinTypes[0],
// senderAddress,
// senderCap,
// streamCreationResult.streamId,
// newStopTime
// )).rejects.toThrowError(
// `${senderCap} is not a valid ObjectId`
// )
// })
// test('extendTransaction should throw error if streamId is not a valid object', async () => {
// const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
// const newStopTime = streamInfo.stopTime + 10
// const senderAddress = await sender.getAddress()
// const streamId = streamCreationResult.streamId + '1'
// await expect(stream.extendTransaction(
// coinTypes[0],
// senderAddress,
// streamCreationResult.senderCap,
// streamId,
// newStopTime
// )).rejects.toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// test('extendTransaction should throw error if newStopTime earlier than the existing stopTime', async () => {
// const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
// const newStopTime = streamInfo.stopTime - 1
// const senderAddress = await sender.getAddress()
// await expect(stream.extendTransaction(
// coinTypes[0],
// senderAddress,
// streamCreationResult.senderCap,
// streamCreationResult.streamId,
// newStopTime
// )).rejects.toThrowError(
// `newStopTime ${newStopTime} is earlier than the stopTime ${streamInfo.stopTime}`
// )
// })
// test('extendTransaction should throw error if newStopTime is too far away', async () => {
// const newStopTime = 253402300799 + 1
// const senderAddress = await sender.getAddress()
// await expect(stream.extendTransaction(
// coinTypes[0],
// senderAddress,
// streamCreationResult.senderCap,
// streamCreationResult.streamId,
// newStopTime
// )).rejects.toThrowError(
// `The time ${newStopTime} is later than 9999/12/31 23:59:59`
// )
// })
// --- pauseable ---
test('the stream is pauseable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.pauseable(streamInfo, senderAddress)).toBe(true)
})
test('the stream is not pauseable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.pauseable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not pauseable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.pauseable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not pauseable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.pauseable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- pauseTransaction ---
test('pauseTransaction works', async () => {
const txb = stream.pauseTransaction(
coinTypes[0],
streamCreationResult.senderCap,
streamCreationResult.streamId
)
const senderAddress = await sender.getAddress()
txb.setSender(senderAddress)
const txBytes = await txb.build({ provider: rpcProvider })
const response = await sender.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
console.log('--- pauseTransaction Response ---')
console.log(response)
})
// test('pauseTransaction should throw error if the senderCap is not valid', () => {
// const senderCap = streamCreationResult.senderCap + 'a'
// expect(() => stream.pauseTransaction(
// coinTypes[0],
// senderCap,
// streamCreationResult.streamId
// )).toThrowError(
// `${senderCap} is not a valid ObjectId`
// )
// })
// test('pauseTransaction should throw error if the streamId is not valid', () => {
// const streamId = streamCreationResult.streamId + 'a'
// expect(() => stream.pauseTransaction(
// coinTypes[0],
// streamCreationResult.senderCap,
// streamId
// )).toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// --- pauseable ---
test('the stream is not pauseable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.pauseable(streamInfo, senderAddress)).toBe(false)
})
test('the stream is not pauseable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.pauseable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not pauseable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.pauseable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not pauseable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.pauseable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- withdrawable ---
test('withdrawable should be 0 when stream is paused', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const withdrawable = stream.withdrawable(streamInfo)
expect(withdrawable).toBe(BigInt(0))
})
// --- resumeTransaction ---
test('resumeTransaction works', async () => {
const txb = stream.resumeTransaction(
coinTypes[0],
streamCreationResult.senderCap,
streamCreationResult.streamId
)
const senderAddress = await sender.getAddress()
txb.setSender(senderAddress)
const txBytes = await txb.build({ provider: rpcProvider })
const response = await sender.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
console.log('--- resumeTransaction Response ---')
console.log(response)
})
// test('resumeTransaction should throw error if the senderCap is not valid', () => {
// const senderCap = streamCreationResult.senderCap + 'a'
// expect(() => stream.resumeTransaction(
// coinTypes[0],
// senderCap,
// streamCreationResult.streamId
// )).toThrowError(
// `${senderCap} is not a valid ObjectId`
// )
// })
// test('resumeTransaction should throw error if the streamId is not valid', () => {
// const streamId = streamCreationResult.streamId + 'a'
// expect(() => stream.resumeTransaction(
// coinTypes[0],
// streamCreationResult.senderCap,
// streamId
// )).toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// --- pauseable ---
test('the stream is pauseable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.pauseable(streamInfo, senderAddress)).toBe(true)
})
test('the stream is not pauseable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.pauseable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not pauseable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.pauseable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not pauseable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.pauseable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- closeable ---
test('the stream is closeable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.closeable(streamInfo, senderAddress)).toBe(true)
})
test('the stream is not closeable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.closeable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not closeable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.closeable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not closeable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.closeable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- recipientModifiable ---
test('the stream is not recipientModifiable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.recipientModifiable(streamInfo, senderAddress)).toBe(false)
})
test('the stream is not recipientModifiable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.recipientModifiable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is recipientModifiable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.recipientModifiable(streamInfo, recipientAddress)).toBe(true)
})
test('the stream is not recipientModifiable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.recipientModifiable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- withdrawable ---
test('withdrawable should be greater than 0 when stream is resumed', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const withdrawable = stream.withdrawable(streamInfo)
expect(withdrawable).toBeGreaterThan(0)
})
// --- withdrawTransaction ---
test('withdrawTransaction works', async () => {
const txb = stream.withdrawTransaction(
coinTypes[0],
streamCreationResult.streamId
)
const recipientAddress = await recipient.getAddress()
txb.setSender(recipientAddress)
txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
const txBytes = await txb.build({ provider: rpcProvider })
const response = await recipient.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
console.log('--- withdrawTransaction Response ---')
console.log(response)
})
// test('withdrawTransaction should throw error if the streamId is not valid', () => {
// const streamId = streamCreationResult.streamId + 'a'
// expect(() => stream.withdrawTransaction(
// coinTypes[0],
// streamId
// )).toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// --- setNewRecipientTransaction ---
test('setNewRecipientTransaction works', async () => {
const anotherRecipientAddress = await anotherRecipient.getAddress()
const txb = stream.setNewRecipientTransaction(
coinTypes[0],
streamCreationResult.streamId,
anotherRecipientAddress
)
const recipientAddress = await recipient.getAddress()
txb.setSender(recipientAddress)
txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
const txBytes = await txb.build({ provider: rpcProvider })
const response = await recipient.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
console.log('--- setNewRecipientTransaction Response ---')
console.log(response)
})
// test('setNewRecipientTransaction should throw error if the streamId is not valid', async () => {
// const anotherRecipientAddress = await anotherRecipient.getAddress()
// const streamId = streamCreationResult.streamId + 'a'
// expect(() => stream.setNewRecipientTransaction(
// coinTypes[0],
// streamId,
// anotherRecipientAddress
// )).toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// test('setNewRecipientTransaction should throw error if the newRecipient is not valid', async () => {
// const anotherRecipientAddress = await anotherRecipient.getAddress() + 'x'
// expect(() => stream.setNewRecipientTransaction(
// coinTypes[0],
// streamCreationResult.streamId,
// anotherRecipientAddress
// )).toThrowError('Invalid Sui address')
// })
// --- recipientModifiable ---
test('the stream is not recipientModifiable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.recipientModifiable(streamInfo, senderAddress)).toBe(false)
})
test('the stream is not recipientModifiable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.recipientModifiable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not recipientModifiable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.recipientModifiable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is recipientModifiable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.recipientModifiable(streamInfo, anotherRecipientAddress)).toBe(true)
})
// --- closeTransaction ---
test('closeTransaction works', async () => {
const txb = stream.closeTransaction(
coinTypes[0],
streamCreationResult.senderCap,
streamCreationResult.streamId
)
const senderAddress = await sender.getAddress()
txb.setSender(senderAddress)
const txBytes = await txb.build({ provider: rpcProvider })
const response = await sender.signAndExecuteTransactionBlock({
transactionBlock: txBytes,
options: {
showObjectChanges: true,
},
})
console.log('--- closeTransaction Response ---')
console.log(response)
})
// test('closeTransaction should throw error if the senderCap is not valid', () => {
// const senderCap = streamCreationResult.senderCap + 'a'
// expect(() => stream.closeTransaction(
// coinTypes[0],
// senderCap,
// streamCreationResult.streamId
// )).toThrowError(
// `${senderCap} is not a valid ObjectId`
// )
// })
// test('closeTransaction should throw error if the streamId is not valid', () => {
// const streamId = streamCreationResult.streamId + 'a'
// expect(() => stream.closeTransaction(
// coinTypes[0],
// streamCreationResult.senderCap,
// streamId
// )).toThrowError(
// `${streamId} is not a valid ObjectId`
// )
// })
// --- pauseable ---
test('the stream is not pauseable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.pauseable(streamInfo, senderAddress)).toBe(false)
})
test('the stream is not pauseable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.pauseable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not pauseable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.pauseable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not pauseable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.pauseable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- closeable ---
test('the stream is not closeable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.closeable(streamInfo, senderAddress)).toBe(false)
})
test('the stream is not closeable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.closeable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not closeable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.closeable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not closeable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.closeable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- recipientModifiable ---
test('the stream is not recipientModifiable for the sender', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const senderAddress = await sender.getAddress()
expect(stream.recipientModifiable(streamInfo, senderAddress)).toBe(false)
})
test('the stream is not recipientModifiable for the admin', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const adminAddress = await admin.getAddress()
expect(stream.recipientModifiable(streamInfo, adminAddress)).toBe(false)
})
test('the stream is not recipientModifiable for the recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const recipientAddress = await recipient.getAddress()
expect(stream.recipientModifiable(streamInfo, recipientAddress)).toBe(false)
})
test('the stream is not recipientModifiable for another recipient', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const anotherRecipientAddress = await anotherRecipient.getAddress()
expect(stream.recipientModifiable(streamInfo, anotherRecipientAddress)).toBe(false)
})
// --- withdrawable ---
test('withdrawable should be 0 when stream is closed', async () => {
const streamInfo = await stream.getStreamById(streamCreationResult.streamId)
const withdrawable = stream.withdrawable(streamInfo)
expect(withdrawable).toBe(BigInt(0))
})
// --- getStreams ---
test('getStreams works', async () => {
const senderAddress = await sender.getAddress()
let streams = await stream.getStreams(senderAddress, StreamDirection.OUT)
console.log(streams)
const recipientAddress = await recipient.getAddress()
streams = await stream.getStreams(recipientAddress, StreamDirection.IN)
console.log('--- getStreams Response ---')
console.log(streams)
})
// test('getStreams throws error is the address is invalid', async () => {
// const senderAddress = await sender.getAddress() + 'a'
// await expect(stream.getStreams(senderAddress, StreamDirection.OUT)).rejects.toThrowError('Invalid Sui address')
// })
// --- getSenderCaps ---
test('getSenderCaps works', async () => {
const senderAddress = await sender.getAddress()
const senderCaps = await stream.getSenderCaps(senderAddress)
console.log('--- senderCaps ---')
console.log(senderCaps)
})
// test('getSenderCaps throws error if the address is invalid', async () => {
// const senderAddress = await sender.getAddress() + 'c'
// await expect(stream.getSenderCaps(senderAddress)).rejects.toThrowError('Invalid Sui address')
// })
// --- getPaginatedSenderCaps ---
test('getPaginatedSenderCaps works', async () => {
const senderAddress = await sender.getAddress()
const paginatedSenderCaps = await stream.getPaginatedSenderCaps(
senderAddress,
{ cursor: null }
)
console.log('--- paginated senderCaps ---')
console.log(paginatedSenderCaps)
})
// test('getPaginatedSenderCaps throws error if the address is invalid', async () => {
// const senderAddress = await sender.getAddress() + 'd'
// await expect(stream.getPaginatedSenderCaps(
// senderAddress,
// { cursor: null }
// )).rejects.toThrowError('Invalid Sui address')
// })
// --- getRecipientCaps ---
test('getRecipientCaps works', async () => {
const recipientAddress = await recipient.getAddress()
const recipientCaps = await stream.getRecipientCaps(recipientAddress)
console.log('--- recipientCaps ---')
console.log(recipientCaps)
})
// --- getPaginatedRecipientCaps ---
test('getPaginatedRecipientCaps works', async () => {
const recipientAddress = await recipient.getAddress()
const paginatedRecipientCaps = await stream.getPaginatedRecipientCaps(
recipientAddress,
{ cursor: null }
)
console.log('--- paginated recipientCaps ---')
console.log(paginatedRecipientCaps)
})
// --- getSupportedCoins ---
test('getSupportedCoins works', async () => {
const coins = await stream.getSupportedCoins()
console.log('--- coins ---')
console.log(coins)
})
// --- getPaginatedSupportedCoins ---
test('getPaginatedSupportedCoins works', async () => {
const paginatedCoins = await stream.getPaginatedSupportedCoins(
{ cursor: null }
)
console.log('--- paginated coins ---')
console.log(paginatedCoins)
})
/* **** admin functions **** */
// --- registerCoinTransaction ---
// test('registerCoinTransaction works', async () => {
// const adminAddress = await admin.getAddress()
// const txb = stream.registerCoinTransaction(
// coinTypes[1],
// 20
// )
// txb.setSender(adminAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await admin.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- registerCoinTransaction Response ---')
// console.log(response)
// })
// test('registerCoinTransaction throws error if coin type is invalid', () => {
// const feePoint = 255
// expect(() => stream.registerCoinTransaction(
// coinTypes[2],
// feePoint
// )).toThrow(
// `${coinTypes[2]} is not in a valid format`
// )
// })
// test('registerCoinTransaction throws error if coin type is invalid', () => {
// const feePoint = 255
// expect(() => stream.registerCoinTransaction(
// coinTypes[3],
// feePoint
// )).toThrow(
// `${coinTypes[3]} is not in a valid format`
// )
// })
// test('registerCoinTransaction throws error if fee point is too large', () => {
// const feePoint = 256
// expect(() => stream.registerCoinTransaction(
// coinTypes[1],
// feePoint
// )).toThrow(
// `The feePoint ${feePoint} exceeds 255`
// )
// })
// test('registerCoinTransaction throws error if fee point is negative', () => {
// const feePoint = -1
// expect(() => stream.registerCoinTransaction(
// coinTypes[1],
// feePoint
// )).toThrow(
// `The number ${feePoint} is negative or not an integer`
// )
// })
test('registerCoinTransaction throws error if fee point not an integer', () => {
const feePoint = 8.8
expect(() => stream.registerCoinTransaction(
coinTypes[1],
feePoint
)).toThrow(
`The number ${feePoint} is negative or not an integer`
)
})
// --- setFeePointTransaction ---
// test('setFeePointTransaction works', async () => {
// const adminAddress = await admin.getAddress()
// const txb = stream.setFeePointTransaction(
// coinTypes[0],
// 10
// )
// txb.setSender(adminAddress)
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await admin.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- setFeePointTransaction Response ---')
// console.log(response)
// })
// test('setFeePointTransaction throws error if fee point is too large', () => {
// const feePoint = 256
// expect(() => stream.setFeePointTransaction(
// coinTypes[1],
// feePoint
// )).toThrow(
// `The feePoint ${feePoint} exceeds 255`
// )
// })
// test('setFeePointTransaction throws error if fee point is negative', () => {
// const feePoint = -1
// expect(() => stream.setFeePointTransaction(
// coinTypes[1],
// feePoint
// )).toThrow(
// `The number ${feePoint} is negative or not an integer`
// )
// })
// test('setFeePointTransaction throws error if fee point not an integer', () => {
// const feePoint = 8.8
// expect(() => stream.setFeePointTransaction(
// coinTypes[1],
// feePoint
// )).toThrow(
// `The number ${feePoint} is negative or not an integer`
// )
// })
// --- setFeeRecipientTransaction ---
// test('setFeeRecipientTransaction works', async () => {
// const adminAddress = await admin.getAddress()
// const senderAddress = await sender.getAddress()
// const txb = stream.setFeeRecipientTransaction(
// senderAddress
// )
// txb.setSender(adminAddress)
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await admin.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- setFeeRecipientTransaction Response ---')
// console.log(response)
// })
// test('setFeeRecipientTransaction throws error if the address is invalid', async () => {
// const senderAddress = await sender.getAddress() + 'd'
// expect(() => stream.setFeeRecipientTransaction(
// senderAddress
// )).toThrowError(
// 'Invalid Sui address'
// )
// })
/* **** end of Admin functions **** */
// below are the non-gas coin test cases
// test('createTransaction works for a non-gas coin type - no need to merge coins', async () => {
// const name = 'second'
// const remark = 'paper_coin stream'
// const depositAmount = BigInt(10000)
// const startTime = Math.floor(Date.now() / 1000) - 10
// const duration = 24 * 60 * 60 // 1 day
// const stopTime = startTime + duration
// const senderAddress = await sender.getAddress()
// const recipientAddress = await recipient.getAddress()
// const txb = await stream.createTransaction(
// coinTypes[1], // PAPER_COIN
// name,
// remark,
// senderAddress,
// recipientAddress,
// depositAmount,
// startTime,
// stopTime
// )
// txb.setSender(senderAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await sender.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- createTransaction response ---')
// console.log(response)
// streamCreationResult = stream.getStreamCreationResult(response as any)
// console.log('--- streamCreationResult ---')
// console.log(streamCreationResult)
// })
// test('createTransaction works for a non-gas coin type - need to merge coins', async () => {
// const name = 'second'
// const remark = 'paper_coin stream'
// const depositAmount = BigInt(200 * 10**8) // 200 PAPER_COIN
// const startTime = Math.floor(Date.now() / 1000) - 10
// const duration = 24 * 60 * 60 // 1 day
// const stopTime = startTime + duration
// const interval = 1 // 1 second
// const senderAddress = await sender.getAddress()
// const recipientAddress = await recipient.getAddress()
// const txb = await stream.createTransaction(
// coinTypes[1], // PAPER_COIN
// name,
// remark,
// senderAddress,
// recipientAddress,
// depositAmount,
// startTime,
// stopTime,
// interval
// )
// txb.setSender(senderAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await sender.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- createTransaction response ---')
// console.log(response)
// streamCreationResult = stream.getStreamCreationResult(response as any)
// console.log('--- streamCreationResult ---')
// console.log(streamCreationResult)
// })
// test('extendTransaction works for a non-gas coin type', async () => {
// const duration = 24 * 60 * 60 // 1 day
// const stopTime = Math.floor(Date.now() / 1000) + duration * 2
// const senderAddress = await sender.getAddress()
// const txb = await stream.extendTransaction(
// coinTypes[1],
// senderAddress,
// streamCreationResult.senderCap,
// streamCreationResult.streamId,
// stopTime
// )
// txb.setSender(senderAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await sender.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- extendTransaction Response ---')
// console.log(response)
// })
// test('pauseTransaction works for a non-gas coin type', async () => {
// const txb = stream.pauseTransaction(
// coinTypes[1],
// streamCreationResult.senderCap,
// streamCreationResult.streamId
// )
// const senderAddress = await sender.getAddress()
// txb.setSender(senderAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await sender.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- pauseTransaction Response ---')
// console.log(response)
// })
// test('resumeTransaction works for a non-gas coin type', async () => {
// const txb = stream.resumeTransaction(
// coinTypes[1],
// streamCreationResult.senderCap,
// streamCreationResult.streamId
// )
// const senderAddress = await sender.getAddress()
// txb.setSender(senderAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await sender.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- resumeTransaction Response ---')
// console.log(response)
// })
// test('withdrawTransaction works for a non-gas coin type', async () => {
// console.log('streamCreationResult:', streamCreationResult);
// const txb = stream.withdrawTransaction(
// coinTypes[1],
// streamCreationResult.streamId
// )
// const recipientAddress = await recipient.getAddress()
// txb.setSender(recipientAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await recipient.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- withdrawTransaction Response ---')
// console.log(response)
// })
// test('setNewRecipientTransaction works for a non-gas coin type', async () => {
// const anotherRecipientAddress = await anotherRecipient.getAddress()
// const txb = stream.setNewRecipientTransaction(
// coinTypes[1],
// streamCreationResult.streamId,
// anotherRecipientAddress
// )
// const recipientAddress = await recipient.getAddress()
// txb.setSender(recipientAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await recipient.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- setNewRecipientTransaction Response ---')
// console.log(response)
// })
// test('closeTransaction works for a non-gas coin type', async () => {
// const txb = stream.closeTransaction(
// coinTypes[1],
// streamCreationResult.senderCap,
// streamCreationResult.streamId
// )
// const senderAddress = await sender.getAddress()
// txb.setSender(senderAddress)
// txb.setGasBudget(30000000) // otherwise error - not able to determine a budget
// const txBytes = await txb.build({ provider: rpcProvider })
// const response = await sender.signAndExecuteTransactionBlock({
// transactionBlock: txBytes,
// options: {
// showObjectChanges: true,
// },
// })
// console.log('--- closeTransaction Response ---')
// console.log(response)
// })
})