-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[@kadena/client-utils] Implement Marmalade functions (Feat) (#1484)
* add marmalade generate contract script * create token and create token id functions * small refactor to create token id and create token * mint token functionality * transfer-create function * get balance function * refactor createToken * index file * added unit testing for createId, create and mint tokens * integration testing; lint and style fixes; index file for marmalade * removed unecessary exports * omit sign in dirty reads * changeset file * marmalade integration testing init * make chain argument declared at top; * ci changes: add apt-get update * default chain 0 * unit testing to meet threshold * lint fixes * fix: minor fixes and comments resolutions * fix: adjusted precision type from number to Pact Int * fix: lint fixes * chore: update the create token capability signature * [@kadena/client-utils] Implement Marmalade functions - additions (#1945) * chore: added more maramalade util functions * chore: align create-token with other functions * fix: linting issues * chore: add update-uri function * chore: format files * [@kadena/client-utils] Implement Marmalade functions - Sale functions (#2055) * chore: added more maramalade util functions * chore: align create-token with other functions * fix: linting issues * feat: added sale functions and tests; chore: updated and cleaned read functions * chore: linting * chore: added script to setup test environment before executing integration tests * chore: lint setup marmalade test env file * chore: gnerate marmalade-v2.policy-manager types * chore: check if conventional and dutch auction have been whitelisted * chore: remove whitelisting sale from test setup script * chore: wait for block time helper function * chore: fix lint issue * chore: enforce failure uri guard if not updatable when using guard policy * chore: rename config to updatableURI * chore: remove guard on local calls * feat: added collection-policy functions * chore: adjust the auction end date in tests * chore: cleanup and stability improvements * fix: more time * chore: simplify local call functions * chore: linting * chore: get quote function and reorganize imports (#2187) --------- Co-authored-by: Ivan Magaš <imagas96@gmail.com>
- Loading branch information
1 parent
07ec969
commit 381a766
Showing
45 changed files
with
6,545 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@kadena/client-utils': patch | ||
--- | ||
|
||
Added marmalade functions and correspondent integration testing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
376 changes: 376 additions & 0 deletions
376
packages/libs/client-utils/src/integration-tests/marmalade-collection-policy.int.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,376 @@ | ||
import type { ChainId } from '@kadena/client'; | ||
import { createSignWithKeypair } from '@kadena/client'; | ||
import { PactNumber } from '@kadena/pactjs'; | ||
import type { IPactInt } from '@kadena/types'; | ||
import { describe, expect, it } from 'vitest'; | ||
import { | ||
createCollection, | ||
createCollectionId, | ||
createToken, | ||
createTokenId, | ||
getCollection, | ||
getCollectionToken, | ||
getTokenBalance, | ||
mintToken, | ||
} from '../marmalade'; | ||
import type { ICreateTokenPolicyConfig } from '../marmalade/config'; | ||
import { NetworkIds } from './support/NetworkIds'; | ||
import { withStepFactory } from './support/helpers'; | ||
import { sourceAccount } from './test-data/accounts'; | ||
|
||
let tokenId: string | undefined; | ||
let collectionId: string | undefined; | ||
let collectionName: string | undefined; | ||
const collectionSize: IPactInt = { int: '0' }; | ||
const chainId = '0' as ChainId; | ||
|
||
const inputs = { | ||
policyConfig: { | ||
collection: true, | ||
} as ICreateTokenPolicyConfig, | ||
collection: { | ||
collectionId, | ||
}, | ||
chainId, | ||
precision: { int: '0' }, | ||
uri: Math.random().toString(), | ||
policies: ['marmalade-v2.collection-policy-v1'], | ||
creator: { | ||
account: sourceAccount.account, | ||
keyset: { | ||
keys: [sourceAccount.publicKey], | ||
pred: 'keys-all' as const, | ||
}, | ||
}, | ||
}; | ||
const config = { | ||
host: 'http://127.0.0.1:8080', | ||
defaults: { | ||
networkId: 'development', | ||
}, | ||
sign: createSignWithKeypair([sourceAccount]), | ||
}; | ||
|
||
describe('createCollectionId', () => { | ||
it('should return a collection id', async () => { | ||
collectionName = `Test Collection #${Math.random().toString()}`; | ||
|
||
collectionId = await createCollectionId({ | ||
collectionName, | ||
chainId, | ||
operator: { | ||
keyset: { | ||
keys: [sourceAccount.publicKey], | ||
pred: 'keys-all' as const, | ||
}, | ||
}, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
expect(collectionId).toBeDefined(); | ||
expect(collectionId).toMatch(/^collection:.{43}$/); | ||
|
||
inputs.collection.collectionId = collectionId; | ||
}); | ||
}); | ||
|
||
describe('createCollection', () => { | ||
it('should create a collection', async () => { | ||
const withStep = withStepFactory(); | ||
|
||
const result = await createCollection( | ||
{ | ||
id: collectionId as string, | ||
name: collectionName as string, | ||
size: collectionSize, | ||
operator: inputs.creator, | ||
chainId, | ||
}, | ||
config, | ||
) | ||
.on( | ||
'sign', | ||
withStep((step, tx) => { | ||
expect(step).toBe(1); | ||
expect(tx.sigs).toHaveLength(1); | ||
expect(tx.sigs[0].sig).toBeTruthy(); | ||
}), | ||
) | ||
.on( | ||
'preflight', | ||
withStep((step, prResult) => { | ||
expect(step).toBe(2); | ||
if (prResult.result.status === 'failure') { | ||
expect(prResult.result.status).toBe('success'); | ||
} else { | ||
expect(prResult.result.data).toBe(true); | ||
} | ||
}), | ||
) | ||
.on( | ||
'submit', | ||
withStep((step, trDesc) => { | ||
expect(step).toBe(3); | ||
expect(trDesc.networkId).toBe(NetworkIds.development); | ||
expect(trDesc.chainId).toBe(chainId); | ||
expect(trDesc.requestKey).toBeTruthy(); | ||
}), | ||
) | ||
.on( | ||
'listen', | ||
withStep((step, sbResult) => { | ||
expect(step).toBe(4); | ||
if (sbResult.result.status === 'failure') { | ||
expect(sbResult.result.status).toBe('success'); | ||
} else { | ||
expect(sbResult.result.data).toBe(true); | ||
} | ||
}), | ||
) | ||
.execute(); | ||
|
||
expect(result).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('createTokenId', () => { | ||
it('should return a token id', async () => { | ||
tokenId = await createTokenId({ | ||
...inputs, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
expect(tokenId).toBeDefined(); | ||
expect(tokenId).toMatch(/^t:.{43}$/); | ||
}); | ||
}); | ||
|
||
describe('createToken', () => { | ||
it('should create a token with policy', async () => { | ||
const withStep = withStepFactory(); | ||
|
||
const tokenId = await createTokenId({ | ||
...inputs, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
expect(tokenId).toBeDefined(); | ||
expect(tokenId).toMatch(/^t:.{43}$/); | ||
|
||
const result = await createToken( | ||
{ | ||
...inputs, | ||
tokenId: tokenId as string, | ||
}, | ||
config, | ||
) | ||
.on( | ||
'sign', | ||
withStep((step, tx) => { | ||
expect(step).toBe(1); | ||
expect(tx.sigs).toHaveLength(1); | ||
expect(tx.sigs[0].sig).toBeTruthy(); | ||
}), | ||
) | ||
.on( | ||
'preflight', | ||
withStep((step, prResult) => { | ||
expect(step).toBe(2); | ||
if (prResult.result.status === 'failure') { | ||
expect(prResult.result.status).toBe('success'); | ||
} else { | ||
expect(prResult.result.data).toBe(true); | ||
} | ||
}), | ||
) | ||
.on( | ||
'submit', | ||
withStep((step, trDesc) => { | ||
expect(step).toBe(3); | ||
expect(trDesc.networkId).toBe(NetworkIds.development); | ||
expect(trDesc.chainId).toBe(chainId); | ||
expect(trDesc.requestKey).toBeTruthy(); | ||
}), | ||
) | ||
.on( | ||
'listen', | ||
withStep((step, sbResult) => { | ||
expect(step).toBe(4); | ||
if (sbResult.result.status === 'failure') { | ||
expect(sbResult.result.status).toBe('success'); | ||
} else { | ||
expect(sbResult.result.data).toBe(true); | ||
} | ||
}), | ||
) | ||
.execute(); | ||
|
||
expect(result).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('mintToken', () => { | ||
it('should mint a token', async () => { | ||
const withStep = withStepFactory(); | ||
|
||
const result = await mintToken( | ||
{ | ||
...inputs, | ||
tokenId: tokenId as string, | ||
accountName: sourceAccount.account, | ||
guard: { | ||
account: sourceAccount.account, | ||
keyset: { | ||
keys: [sourceAccount.publicKey], | ||
pred: 'keys-all' as const, | ||
}, | ||
}, | ||
amount: new PactNumber(1).toPactDecimal(), | ||
}, | ||
config, | ||
) | ||
.on( | ||
'sign', | ||
withStep((step, tx) => { | ||
expect(step).toBe(1); | ||
expect(tx.sigs).toHaveLength(1); | ||
expect(tx.sigs[0].sig).toBeTruthy(); | ||
}), | ||
) | ||
.on( | ||
'preflight', | ||
withStep((step, prResult) => { | ||
expect(step).toBe(2); | ||
if (prResult.result.status === 'failure') { | ||
expect(prResult.result.status).toBe('success'); | ||
} else { | ||
expect(prResult.result.data).toBe(true); | ||
} | ||
}), | ||
) | ||
.on( | ||
'submit', | ||
withStep((step, trDesc) => { | ||
expect(step).toBe(3); | ||
expect(trDesc.networkId).toBe(NetworkIds.development); | ||
expect(trDesc.chainId).toBe(chainId); | ||
expect(trDesc.requestKey).toBeTruthy(); | ||
}), | ||
) | ||
.on( | ||
'listen', | ||
withStep((step, sbResult) => { | ||
expect(step).toBe(4); | ||
if (sbResult.result.status === 'failure') { | ||
expect(sbResult.result.status).toBe('success'); | ||
} else { | ||
expect(sbResult.result.data).toBe(true); | ||
} | ||
}), | ||
) | ||
.execute(); | ||
|
||
expect(result).toBe(true); | ||
|
||
const balance = await getTokenBalance({ | ||
accountName: sourceAccount.account, | ||
chainId, | ||
tokenId: tokenId as string, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
expect(balance).toBe(1); | ||
}); | ||
it('should throw error when non-existent token is minted', async () => { | ||
const nonExistingTokenId = 'non-existing-token'; | ||
const task = mintToken( | ||
{ | ||
...inputs, | ||
tokenId: nonExistingTokenId, | ||
accountName: sourceAccount.account, | ||
guard: { | ||
account: sourceAccount.account, | ||
keyset: { | ||
keys: [sourceAccount.publicKey], | ||
pred: 'keys-all' as const, | ||
}, | ||
}, | ||
amount: new PactNumber(1).toPactDecimal(), | ||
}, | ||
config, | ||
); | ||
|
||
await expect(() => task.execute()).rejects.toThrowError( | ||
new Error('with-read: row not found: non-existing-token'), | ||
); | ||
}); | ||
}); | ||
|
||
describe('getCollection', () => { | ||
it('should get the collection details', async () => { | ||
const result = await getCollection({ | ||
chainId, | ||
collectionId: collectionId as string, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
id: collectionId, | ||
'max-size': { | ||
int: Number(collectionSize.int), | ||
}, | ||
name: collectionName, | ||
'operator-guard': inputs.creator.keyset, | ||
size: { | ||
int: 1, | ||
}, | ||
}); | ||
}); | ||
it('should throw an error if token does not exist', async () => { | ||
const nonExistingTokenId = 'non-existing-collection'; | ||
const task = getCollection({ | ||
collectionId: nonExistingTokenId, | ||
chainId, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
await expect(() => Promise.resolve(task)).rejects.toThrowError( | ||
new Error(`read: row not found: non-existing-collection`), | ||
); | ||
}); | ||
}); | ||
|
||
describe('getCollectionToken', () => { | ||
it('should get the collection token details', async () => { | ||
const result = await getCollectionToken({ | ||
chainId, | ||
tokenId: tokenId as string, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
id: tokenId, | ||
'collection-id': collectionId, | ||
}); | ||
}); | ||
it('should throw an error if token does not exist', async () => { | ||
const nonExistingTokenId = 'non-existing-token'; | ||
const task = getCollectionToken({ | ||
chainId, | ||
tokenId: nonExistingTokenId, | ||
networkId: config.defaults.networkId, | ||
host: config.host, | ||
}); | ||
|
||
await expect(() => Promise.resolve(task)).rejects.toThrowError( | ||
new Error(`read: row not found: non-existing-token`), | ||
); | ||
}); | ||
}); |
Oops, something went wrong.