Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
194 additions
and
0 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,194 @@ | ||
/* eslint-disable sonarjs/no-duplicate-string */ | ||
import { Cardano, metadatum, nativeScriptPolicyId } from '@cardano-sdk/core'; | ||
import { FinalizeTxProps, PersonalWallet } from '@cardano-sdk/wallet'; | ||
import { InitializeTxProps } from '@cardano-sdk/tx-construction'; | ||
import { KeyRole, TransactionSigner, util } from '@cardano-sdk/key-management'; | ||
import { Metadatum, TokenMap } from '@cardano-sdk/core/dist/cjs/Cardano'; | ||
import { burnTokens, createStandaloneKeyAgent, submitAndConfirm, walletReady } from '../../util'; | ||
import { createLogger } from '@cardano-sdk/util-dev'; | ||
import { firstValueFrom } from 'rxjs'; | ||
import { getEnv, getWallet, walletVariables } from '../../../src'; | ||
|
||
const env = getEnv(walletVariables); | ||
const logger = createLogger(); | ||
|
||
type HandleMetadata = { | ||
[policyId: string]: { | ||
[handleName: string]: { | ||
augmentations: []; | ||
core: { | ||
handleEncoding: string; | ||
og: number; | ||
prefix: string; | ||
termsofuse: string; | ||
version: number; | ||
}; | ||
description: string; | ||
image: string; | ||
name: string; | ||
website: string; | ||
}; | ||
}; | ||
}; | ||
|
||
const createHandleMetadata = (handlePolicyId: string, handleNames: string[]): HandleMetadata => { | ||
const result: HandleMetadata[0] = {}; | ||
for (const key of handleNames) { | ||
result[key] = { | ||
augmentations: [], | ||
core: { | ||
handleEncoding: 'utf-8', | ||
og: 0, | ||
prefix: '$', | ||
termsofuse: 'https://cardanofoundation.org/en/terms-and-conditions/', | ||
version: 0 | ||
}, | ||
description: 'The Handle Standard', | ||
image: 'ipfs://some-hash', | ||
name: '$handle1', | ||
website: 'https://cardano.org/' | ||
}; | ||
} | ||
return { [handlePolicyId]: result }; | ||
}; | ||
|
||
describe('Ada handle', () => { | ||
let wallet: PersonalWallet; | ||
let wallet2: PersonalWallet; | ||
let policySigner: TransactionSigner; | ||
let policyId: Cardano.PolicyId; | ||
let policyScript: Cardano.NativeScript; | ||
let assetIds: Cardano.AssetId[]; | ||
|
||
const assetNames = ['6861646e6c6531', '6861646e6c6532', '6861646e6c6533']; | ||
let walletAddress: Cardano.PaymentAddress; | ||
const coins = 10_000_000n; // number of coins to use in each transaction | ||
|
||
const mint = async (tokens: Cardano.TokenMap, txMetadatum: Cardano.Metadatum) => { | ||
const auxiliaryData = { | ||
blob: new Map([[721n, txMetadatum]]) | ||
}; | ||
|
||
const txProps: InitializeTxProps = { | ||
auxiliaryData, | ||
mint: tokens, | ||
outputs: new Set([ | ||
{ | ||
address: walletAddress, | ||
value: { | ||
assets: tokens, | ||
coins | ||
} | ||
} | ||
]), | ||
witness: { extraSigners: [policySigner], scripts: [policyScript] } | ||
}; | ||
|
||
const unsignedTx = await wallet.initializeTx(txProps); | ||
|
||
const finalizeProps: FinalizeTxProps = { | ||
auxiliaryData, | ||
tx: unsignedTx, | ||
witness: { extraSigners: [policySigner], scripts: [policyScript] } | ||
}; | ||
|
||
const signedTx = await wallet.finalizeTx(finalizeProps); | ||
await submitAndConfirm(wallet, signedTx); | ||
}; | ||
|
||
beforeAll(async () => { | ||
wallet = (await getWallet({ env, idx: 0, logger, name: 'Minting Wallet', polling: { interval: 50 } })).wallet; | ||
await walletReady(wallet, coins); | ||
wallet2 = (await getWallet({ env, idx: 1, logger, name: 'Receiving Wallet', polling: { interval: 50 } })).wallet; | ||
await walletReady(wallet, coins); | ||
const keyAgent = await createStandaloneKeyAgent( | ||
env.KEY_MANAGEMENT_PARAMS.mnemonic.split(' '), | ||
await firstValueFrom(wallet.genesisParameters$), | ||
await wallet.keyAgent.getBip32Ed25519() | ||
); | ||
|
||
const derivationPath = { | ||
index: 2, | ||
role: KeyRole.External | ||
}; | ||
const pubKey = await keyAgent.derivePublicKey(derivationPath); | ||
const keyHash = await keyAgent.bip32Ed25519.getPubKeyHash(pubKey); | ||
policySigner = new util.KeyAgentTransactionSigner(keyAgent, derivationPath); | ||
policyScript = { | ||
__type: Cardano.ScriptType.Native, | ||
kind: Cardano.NativeScriptKind.RequireAllOf, | ||
scripts: [ | ||
{ | ||
__type: Cardano.ScriptType.Native, | ||
keyHash, | ||
kind: Cardano.NativeScriptKind.RequireSignature | ||
} | ||
] | ||
}; | ||
policyId = nativeScriptPolicyId(policyScript); | ||
assetIds = [Cardano.AssetId(`${policyId}${assetNames[0]}`), Cardano.AssetId(`${policyId}${assetNames[1]}`)]; | ||
walletAddress = (await firstValueFrom(wallet.addresses$))[0].address; | ||
}); | ||
|
||
afterEach(async () => { | ||
await burnTokens({ | ||
policySigners: [policySigner], | ||
scripts: [policyScript], | ||
wallet | ||
}); | ||
await burnTokens({ | ||
policySigners: [policySigner], | ||
scripts: [policyScript], | ||
wallet: wallet2 | ||
}); | ||
}); | ||
|
||
afterAll(async () => { | ||
wallet.shutdown(); | ||
wallet2.shutdown(); | ||
}); | ||
|
||
it('mint and send handle', async () => { | ||
const tokens = new Map([ | ||
[assetIds[0], 1n], | ||
[assetIds[1], 1n] | ||
]); | ||
const txMetadatum = metadatum.jsonToMetadatum(createHandleMetadata(policyId, ['handle1', 'handle2'])); | ||
await mint(tokens, txMetadatum); | ||
let handles = await firstValueFrom(wallet.balance.utxo.available$); | ||
let handles2 = await firstValueFrom(wallet2.balance.utxo.available$); | ||
expect(handles.assets?.size).toEqual(2); | ||
expect(handles2.assets?.size).toBeUndefined(); | ||
|
||
const token = new Map([[assetIds[0], 1n]]); | ||
const destAddresses = (await firstValueFrom(wallet2.addresses$))[0].address; | ||
const txBuilder = wallet.createTxBuilder(); | ||
const { tx } = await txBuilder | ||
.addOutput(await txBuilder.buildOutput().address(destAddresses).coin(2_000_000n).assets(token).build()) | ||
.build() | ||
.sign(); | ||
await wallet.submitTx(tx); | ||
|
||
handles = await firstValueFrom(wallet.balance.utxo.available$); | ||
handles2 = await firstValueFrom(wallet2.balance.utxo.available$); | ||
expect(handles.assets?.size).toEqual(1); | ||
expect(handles2.assets?.size).toEqual(1); | ||
}); | ||
|
||
it('mint same handle again', async () => { | ||
const tokens: TokenMap = new Map([[assetIds[0], 1n]]); | ||
const txMetadatum: Metadatum = metadatum.jsonToMetadatum(createHandleMetadata(policyId, ['handle1'])); | ||
await mint(tokens, txMetadatum); | ||
await mint(tokens, txMetadatum); | ||
const handles = await firstValueFrom(wallet.balance.utxo.available$); | ||
expect(handles.assets?.values().next().value).toEqual(2n); | ||
}); | ||
|
||
it('double minted handles one tx', async () => { | ||
const tokens = new Map([[assetIds[0], 2n]]); | ||
const txMetadatum: Metadatum = metadatum.jsonToMetadatum(createHandleMetadata(policyId, ['handle1'])); | ||
await mint(tokens, txMetadatum); | ||
const handles = await firstValueFrom(wallet.balance.utxo.available$); | ||
expect(handles.assets?.values().next().value).toEqual(2n); | ||
}); | ||
}); |