UNPKG

@radixdlt/atom-transaction-mapping

Version:
197 lines (173 loc) 5.27 kB
import { makeSimpleTransitioner, makeTransitioner, } from '../src/toAtom/fungibleParticleTransitioner' import { AnySpunParticle, ParticleBase, Spin, spunDownParticle, spunUpParticle, } from '@radixdlt/atom' import { Amount, AmountT } from '@radixdlt/primitives' import { UInt256 } from '@radixdlt/uint256' import { v4 as uuidv4 } from 'uuid' import { exactlyContainParticles } from '../../atom/test/helpers/particles' import { two, nine, one, ten } from '@radixdlt/primitives/src/amount' import { ok } from 'neverthrow' import { SpunParticleT } from '@radixdlt/atom/src/particles/_types' describe('fungibleParticleTransitioner', () => { const eleven = Amount.inSmallestDenomination(UInt256.valueOf(11)) type TestParticle = ParticleBase & { amount: AmountT id: string isChangeReturnedToSender: boolean } const testParticle = ( amount: number | AmountT, id?: string, isChangeReturnedToSender?: boolean, ): TestParticle => { const id_ = id ?? uuidv4() const amount_ = typeof amount === 'number' ? Amount.inSmallestDenomination(UInt256.valueOf(amount)) : amount return <TestParticle>{ amount: amount_, id: id_, isChangeReturnedToSender: isChangeReturnedToSender ?? false, equals: (other) => (other as TestParticle).id === id_, } } const transitioner = makeSimpleTransitioner<TestParticle, TestParticle>({ inputAmountMapper: (p) => p.amount, inputCreator: (amount) => /* From */ testParticle(amount), outputCreator: (amount) => /* To */ testParticle(amount), }) it('should create a transition with two particles is output when TWO to 2', () => { const particle = testParticle(2) const spunParticles = transitioner .transition({ currentParticles: [particle], totalAmountToTransfer: two, }) ._unsafeUnwrap() expect(spunParticles.length).toBe(2) const spunParticle0 = spunParticles[0] expect(spunParticle0.particle.equals(particle)).toBe(true) expect(spunParticle0.spin).toBe(Spin.DOWN) const spunParticle1 = spunParticles[1] expect(spunParticle1.spin).toBe(Spin.UP) expect(spunParticle1.particle.equals(particle)).toBe(false) expect( (spunParticle1.particle as TestParticle).amount.equals(two), ).toBe(true) }) type SpunTestParticle = SpunParticleT<TestParticle> const upTP = (tp: TestParticle): SpunTestParticle => spunUpParticle(tp) const downTP = (tp: TestParticle): SpunTestParticle => spunDownParticle(tp) const expectTransition = ( input: Readonly<{ actual: AnySpunParticle[] expected: SpunTestParticle[] }>, ): void => { const match = exactlyContainParticles({ actual: input.actual, expected: input.expected.map((p) => p.eraseToAny()), }) expect(match).toBe(true) } it('should work with many particle and change', () => { const outCounter = 0 const transitioner = makeTransitioner<TestParticle, TestParticle>({ inputAmountMapper: (p) => p.amount, inputCreator: (amount, from: TestParticle) => /* From */ ok( testParticle(amount, from.id.toUpperCase(), true), ), outputCreator: (amount) => /* To */ ok(testParticle(amount, `up${outCounter}`)), }) const a = testParticle(1, 'a') const b = testParticle(2, 'b') const c = testParticle(3, 'c') const d = testParticle(4, 'd') const spunParticles = transitioner .transition({ currentParticles: [a, b, c, d], totalAmountToTransfer: nine, }) ._unsafeUnwrap() expectTransition({ actual: spunParticles, expected: [ upTP(testParticle(nine, 'up0', false)), downTP(a), downTP(b), downTP(c), downTP(d), upTP(testParticle(one, 'D', true)), ], }) }) it('should work with many particle and no change', () => { const transitioner = makeTransitioner<TestParticle, TestParticle>({ inputAmountMapper: (p) => p.amount, inputCreator: (amount, from: TestParticle) => /* From */ ok(testParticle(amount, from.id.toUpperCase())), outputCreator: (amount) => /* To */ ok(testParticle(amount, `up0`)), }) const a = testParticle(1, 'a') const b = testParticle(2, 'b') const c = testParticle(3, 'c') const d = testParticle(4, 'd') const spunParticles = transitioner .transition({ currentParticles: [a, b, c, d], totalAmountToTransfer: ten, }) ._unsafeUnwrap() expectTransition({ actual: spunParticles, expected: [ upTP(testParticle(nine, 'up0')), downTP(a), downTP(b), downTP(c), downTP(d), ], }) }) it('should fail if insufficient funds with single particle', () => { const particle = testParticle(1) const transitionResult = transitioner.transition({ currentParticles: [particle], totalAmountToTransfer: two, }) transitionResult.match( () => { throw Error('expected error, but got none') }, (e) => expect(e.message).toBe(`Insufficient balance.`), ) }) it('should fail if insufficient funds with many particle', () => { const transitionResult = transitioner.transition({ currentParticles: [ testParticle(1), testParticle(2), testParticle(3), testParticle(4), ], totalAmountToTransfer: eleven, }) transitionResult.match( () => { throw Error('expected error, but got none') }, (e) => expect(e.message).toBe(`Insufficient balance.`), ) }) })