From 79b538c0d3aa7c79dd93d11e73399e78b8af594b Mon Sep 17 00:00:00 2001 From: wfalcon0x Date: Tue, 13 Feb 2024 17:11:11 +0000 Subject: [PATCH 1/3] add flix registry smart contract, to store interaction templates on chain --- registry/cadence/README.md | 6 + registry/cadence/contracts/flix_registry.cdc | 136 +++++++ .../contracts/flix_registry_interface.cdc | 103 +++++ .../cadence/contracts/flix_schema_draft.cdc | 49 +++ .../cadence/contracts/flix_schema_v1_1_0.cdc | 202 ++++++++++ registry/cadence/scripts/get_all_alias.cdc | 11 + .../cadence/scripts/get_registry_size.cdc | 13 + registry/cadence/scripts/lookup.cdc | 11 + registry/cadence/scripts/resolve.cdc | 11 + registry/cadence/test/flix_registry_test.cdc | 338 ++++++++++++++++ .../cadence/test/flix_schema_v1_1_0_test.cdc | 365 ++++++++++++++++++ .../cadence/transactions/create_registry.cdc | 17 + .../cadence/transactions/deprecate_flix.cdc | 11 + registry/cadence/transactions/link_alias.cdc | 11 + .../cadence/transactions/publish_flix.cdc | 13 + .../transactions/publish_flix_v1_1_0.cdc | 12 + registry/cadence/transactions/remove_flix.cdc | 14 + .../cadence/transactions/unlink_alias.cdc | 11 + registry/flow.json | 53 +++ 19 files changed, 1387 insertions(+) create mode 100644 registry/cadence/README.md create mode 100644 registry/cadence/contracts/flix_registry.cdc create mode 100644 registry/cadence/contracts/flix_registry_interface.cdc create mode 100644 registry/cadence/contracts/flix_schema_draft.cdc create mode 100644 registry/cadence/contracts/flix_schema_v1_1_0.cdc create mode 100644 registry/cadence/scripts/get_all_alias.cdc create mode 100644 registry/cadence/scripts/get_registry_size.cdc create mode 100644 registry/cadence/scripts/lookup.cdc create mode 100644 registry/cadence/scripts/resolve.cdc create mode 100644 registry/cadence/test/flix_registry_test.cdc create mode 100644 registry/cadence/test/flix_schema_v1_1_0_test.cdc create mode 100644 registry/cadence/transactions/create_registry.cdc create mode 100644 registry/cadence/transactions/deprecate_flix.cdc create mode 100644 registry/cadence/transactions/link_alias.cdc create mode 100644 registry/cadence/transactions/publish_flix.cdc create mode 100644 registry/cadence/transactions/publish_flix_v1_1_0.cdc create mode 100644 registry/cadence/transactions/remove_flix.cdc create mode 100644 registry/cadence/transactions/unlink_alias.cdc create mode 100644 registry/flow.json diff --git a/registry/cadence/README.md b/registry/cadence/README.md new file mode 100644 index 0000000..7704d5c --- /dev/null +++ b/registry/cadence/README.md @@ -0,0 +1,6 @@ +### 👋 Welcome Flix Developer! + +To run the tests execute the following command: +```bash +flow test --cover --covercode="contracts" cadence/test/flix_registry_test.cdc +``` diff --git a/registry/cadence/contracts/flix_registry.cdc b/registry/cadence/contracts/flix_registry.cdc new file mode 100644 index 0000000..121040c --- /dev/null +++ b/registry/cadence/contracts/flix_registry.cdc @@ -0,0 +1,136 @@ +import "FLIXRegistryInterface" + +access(all) +contract FLIXRegistry: FLIXRegistryInterface { + + access(all) + event ContractInitialized() + + access(all) + event RegistryCreated(name: String) + + access(all) + event Published(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String, id: String, cadenceBodyHash: String) + + access(all) + event Removed(registryOwner: Address, registryName: String, registryUuid: UInt64, id: String) + + access(all) + event Deprecated(registryOwner: Address, registryName: String, registryUuid: UInt64, id: String) + + access(all) + event AliasLinked(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String, id: String) + + access(all) + event AliasUnlinked(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String) + + access(all) + enum FLIXStatus: UInt8 { + + access(all) + case active + + access(all) + case deprecated + } + + access(all) + resource Registry: FLIXRegistryInterface.Queryable, FLIXRegistryInterface.Removable, FLIXRegistryInterface.Admin { + + access(account) var flixes: {String: {FLIXRegistryInterface.InteractionTemplate}} + access(account) var aliases: {String: String} + access(account) var cadenceBodyHashes: {String: {FLIXRegistryInterface.InteractionTemplate}} + access(account) let name: String + + access(all) + fun getName(): String { + return self.name + } + + access(all) + fun publish(alias: String, flix: {FLIXRegistryInterface.InteractionTemplate}) { + self.flixes[flix.getId()] = flix + self.aliases[alias] = flix.getId() + self.cadenceBodyHashes[flix.getCadenceBodyHash()] = flix + emit Published(registryOwner: self.owner!.address, registryName: self.name, registryUuid: self.uuid, alias: alias, id: flix.getId(), cadenceBodyHash: flix.getCadenceBodyHash()) + } + + access(all) + fun link(alias: String, id: String) { + self.aliases[alias] = id + emit AliasLinked(registryOwner: self.owner!.address, registryName: self.name, registryUuid: self.uuid, alias: alias, id: id) + } + + access(all) + fun unlink(alias: String) { + self.aliases.remove(key: alias) + emit AliasUnlinked(registryOwner: self.owner!.address, registryName: self.name, registryUuid: self.uuid, alias: alias) + } + + access(all) + fun lookup(idOrAlias: String): {FLIXRegistryInterface.InteractionTemplate}? { + if self.aliases.containsKey(idOrAlias) { + return self.flixes[self.aliases[idOrAlias]!] + } + return self.flixes[idOrAlias] + } + + access(all) + fun resolve(cadenceBodyHash: String): {FLIXRegistryInterface.InteractionTemplate}? { + return self.cadenceBodyHashes[cadenceBodyHash] + } + + access(all) + fun deprecate(idOrAlias: String) { + var flix = self.lookup(idOrAlias: idOrAlias) ?? panic("FLIX does not exist with the given id or alias: ".concat(idOrAlias)) + flix.status = FLIXStatus.deprecated + self.flixes[flix.getId()] = flix + emit Deprecated(registryOwner: self.owner!.address, registryName: self.name, registryUuid: self.uuid, id: flix.getId()) + } + + access(all) + fun remove(id: String): {FLIXRegistryInterface.InteractionTemplate}? { + let removed = self.flixes.remove(key: id) + if(removed != nil) { emit Removed(registryOwner: self.owner!.address, registryName: self.name, registryUuid: self.uuid, id: id) } + return removed + } + + access(all) + fun getIds(): [String] { + return self.flixes.keys + } + + access(all) + fun getAllAlias(): {String: String} { + return self.aliases + } + + init(name: String) { + self.name = name + self.flixes = {} + self.aliases = {} + self.cadenceBodyHashes = {} + emit RegistryCreated(name: name) + } + } + + access(all) + fun createRegistry(name: String): @Registry { + return <- create Registry(name: name) + } + + access(all) + fun PublicPath(name: String): PublicPath { + return PublicPath(identifier: "flix_".concat(name))! + } + + access(all) + fun StoragePath(name: String): StoragePath { + return StoragePath(identifier: "flix_".concat(name))! + } + + init() { + emit ContractInitialized() + } + +} diff --git a/registry/cadence/contracts/flix_registry_interface.cdc b/registry/cadence/contracts/flix_registry_interface.cdc new file mode 100644 index 0000000..672bf41 --- /dev/null +++ b/registry/cadence/contracts/flix_registry_interface.cdc @@ -0,0 +1,103 @@ +access(all) +contract interface FLIXRegistryInterface { + + access(all) + event ContractInitialized() + + access(all) + event RegistryCreated(name: String) + + access(all) + event Published(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String, id: String, cadenceBodyHash: String) + + access(all) + event Removed(registryOwner: Address, registryName: String, registryUuid: UInt64, id: String) + + access(all) + event Deprecated(registryOwner: Address, registryName: String, registryUuid: UInt64, id: String) + + access(all) + event AliasLinked(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String, id: String) + + access(all) + event AliasUnlinked(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String) + + access(all) + enum FLIXStatus: UInt8 { + + access(all) + case active + + access(all) + case deprecated + } + + access(all) + struct interface InteractionTemplate { + access(all) + fun getId(): String + + access(all) + fun getVersion(): String + + access(all) + fun getCadenceBodyHash(): String + + pub(set) + var status: FLIXStatus + + access(all) + fun getData(): AnyStruct + } + + access(all) + resource interface Queryable{ + access(all) + fun getName(): String + + access(all) + fun resolve(cadenceBodyHash: String): {FLIXRegistryInterface.InteractionTemplate}? + + access(all) + fun lookup(idOrAlias: String): {FLIXRegistryInterface.InteractionTemplate}? + + access(all) + fun getIds(): [String] + + access(all) + fun getAllAlias(): {String: String} + } + + access(all) + resource interface Admin { + + // Add the flix to the registry and add or update the alias to point to this flix + access(all) + fun publish(alias: String, flix: {FLIXRegistryInterface.InteractionTemplate}) + + access(all) + fun link(alias: String, id: String) + + access(all) + fun unlink(alias: String) + + access(all) + fun deprecate(idOrAlias: String) + } + + access(all) + resource interface Removable { + access(all) + fun remove(id: String): AnyStruct? + } + + access(all) + resource Registry: Queryable, Removable, Admin { + access(all) + fun getName(): String + } + + access(all) + fun createRegistry(name: String): @Registry + +} \ No newline at end of file diff --git a/registry/cadence/contracts/flix_schema_draft.cdc b/registry/cadence/contracts/flix_schema_draft.cdc new file mode 100644 index 0000000..12349ab --- /dev/null +++ b/registry/cadence/contracts/flix_schema_draft.cdc @@ -0,0 +1,49 @@ +import "FLIXRegistryInterface" +import "FLIXRegistry" + +access(all) +contract FLIXSchema_draft { + + access(all) + struct FLIX: FLIXRegistryInterface.InteractionTemplate { + access(all) + let id: String + + access(all) + let data: AnyStruct + + access(all) + let cadenceBodyHash: String + + access(all) + fun getId(): String { + return self.id + } + + access(all) + fun getData(): AnyStruct { + return self.data + } + + access(all) + fun getVersion(): String { + return "draft" + } + + access(all) + fun getCadenceBodyHash(): String { + return self.cadenceBodyHash + } + + pub(set) + var status: FLIXRegistryInterface.FLIXStatus + + init(id: String, data: AnyStruct, cadenceBodyHash: String) { + self.id = id + self.data = data + self.cadenceBodyHash = cadenceBodyHash + self.status = FLIXRegistry.FLIXStatus.active + } + } + +} \ No newline at end of file diff --git a/registry/cadence/contracts/flix_schema_v1_1_0.cdc b/registry/cadence/contracts/flix_schema_v1_1_0.cdc new file mode 100644 index 0000000..532cb0f --- /dev/null +++ b/registry/cadence/contracts/flix_schema_v1_1_0.cdc @@ -0,0 +1,202 @@ +import "FLIXRegistryInterface" +import "FLIXRegistry" + +access(all) +contract FLIXSchema_v1_1_0 { + + access(all) + struct FLIX: FLIXRegistryInterface.InteractionTemplate { + access(all) + let id: String + + access(all) + let data: Data + + access(all) + let cadenceBodyHash: String + + access(all) + fun getId(): String { + return self.id + } + + access(all) + fun getData(): Data { + return self.data + } + + access(all) + fun getVersion(): String { + return "1.1.0" + } + + access(all) + fun getCadenceBodyHash(): String { + return self.cadenceBodyHash + } + + access(all) + fun getStatus(): FLIXRegistryInterface.FLIXStatus { + return self.status + } + + pub(set) + var status: FLIXRegistryInterface.FLIXStatus + + init(id: String, data: Data, cadenceBodyHash: String) { + self.id = id + self.data = data + self.cadenceBodyHash = cadenceBodyHash + self.status = FLIXRegistry.FLIXStatus.active + } + } + + access(all) struct Data { + access(all) var type: String + access(all) var interface: String + access(all) var messages: [Message] + access(all) var cadence: Cadence + access(all) var dependencies: [Dependency] + access(all) var parameters: [Parameter] + + init(type: String, interface: String, messages: [Message], cadence: Cadence, dependencies: [Dependency], parameters: [Parameter]) { + self.type = type + self.interface = interface + self.messages = messages + self.cadence = cadence + self.dependencies = dependencies + self.parameters = parameters + } + } + + access(all) struct Message { + access(all) var key: String + access(all) var i18n: [I18n] + + init(key: String, i18n: [I18n]) { + self.key = key + self.i18n = i18n + } + } + + access(all) struct I18n { + access(all) var tag: String + access(all) var translation: String + + init(tag: String, translation: String) { + self.tag = tag + self.translation = translation + } + } + + access(all) struct Cadence { + access(all) var body: String + access(all) var networkPins: [NetworkPin] + + init(body: String, networkPins: [NetworkPin]) { + self.body = body + self.networkPins = networkPins + } + } + + access(all) struct NetworkPin { + access(all) var network: String + access(all) var pinSelf: String + + init(network: String, pinSelf: String) { + self.network = network + self.pinSelf = pinSelf + } + } + + access(all) struct Dependency { + access(all) var contracts: [Contract] + + init(contracts: [Contract]) { + self.contracts = contracts + } + } + + access(all) struct Contract { + access(all) var contract: String + access(all) var networks: [Network] + + init(contract: String, networks: [Network]) { + self.contract = contract + self.networks = networks + } + } + + access(all) struct Network { + access(all) var network: String + access(all) var address: String + access(all) var dependencyPinBlockHeight: UInt64 + access(all) var dependencyPin: DependencyPin + + init(network: String, address: String, dependencyPinBlockHeight: UInt64, dependencyPin: DependencyPin) { + self.network = network + self.address = address + self.dependencyPinBlockHeight = dependencyPinBlockHeight + self.dependencyPin = dependencyPin + } + } + + access(all) struct DependencyPin { + access(all) var pin: String + access(all) var pinSelf: String + access(all) var pinContractName: String + access(all) var pinContractAddress: String + access(all) var imports: [Import] + + init(pin: String, pinSelf: String, pinContractName: String, pinContractAddress: String, imports: [Import]) { + self.pin = pin + self.pinSelf = pinSelf + self.pinContractName = pinContractName + self.pinContractAddress = pinContractAddress + self.imports = imports + } + } + + access(all) struct Import { + access(all) var pin: String + access(all) var pinSelf: String + access(all) var pinContractName: String + access(all) var pinContractAddress: String + access(all) var imports: [Import] + + init(pin: String, pinSelf: String, pinContractName: String, pinContractAddress: String, imports: [Import]) { + self.pin = pin + self.pinSelf = pinSelf + self.pinContractName = pinContractName + self.pinContractAddress = pinContractAddress + self.imports = imports + } + } + + access(all) struct Parameter { + access(all) var label: String + access(all) var index: Int + access(all) var type: String + access(all) var messages: [Message] + access(all) var balance: [Balance] + + init(label: String, index: Int, type: String, messages: [Message], balance: [Balance]) { + self.label = label + self.index = index + self.type = type + self.messages = messages + self.balance = balance + } + } + + access(all) struct Balance { + access(all) var network: String + access(all) var pin: String + + init(network: String, pin: String) { + self.network = network + self.pin = pin + } + } + +} \ No newline at end of file diff --git a/registry/cadence/scripts/get_all_alias.cdc b/registry/cadence/scripts/get_all_alias.cdc new file mode 100644 index 0000000..8fcf32c --- /dev/null +++ b/registry/cadence/scripts/get_all_alias.cdc @@ -0,0 +1,11 @@ +import "FLIXRegistry" +import "FLIXRegistryInterface" + +pub fun main(accountAddress: Address, registryName: String): {String: String} { + let account = getAccount(accountAddress) + let registry = account.getCapability(FLIXRegistry.PublicPath(name: registryName)) + .borrow<&FLIXRegistry.Registry{FLIXRegistryInterface.Queryable}>() + ?? panic("Could not borrow a reference to the Registry") + + return registry.getAllAlias() +} \ No newline at end of file diff --git a/registry/cadence/scripts/get_registry_size.cdc b/registry/cadence/scripts/get_registry_size.cdc new file mode 100644 index 0000000..24873a5 --- /dev/null +++ b/registry/cadence/scripts/get_registry_size.cdc @@ -0,0 +1,13 @@ +import "FLIXRegistry" +import "FLIXRegistryInterface" + +pub fun main(address: Address, registryName: String): Int { + let account = getAccount(address) + let registry = account.getCapability(FLIXRegistry.PublicPath(name: registryName)) + .borrow<&FLIXRegistry.Registry{FLIXRegistryInterface.Queryable}>() + ?? panic("Could not borrow a reference to the Registry") + + assert(registryName == registry.getName()) + + return registry.getIds().length +} \ No newline at end of file diff --git a/registry/cadence/scripts/lookup.cdc b/registry/cadence/scripts/lookup.cdc new file mode 100644 index 0000000..70ad998 --- /dev/null +++ b/registry/cadence/scripts/lookup.cdc @@ -0,0 +1,11 @@ +import "FLIXRegistry" +import "FLIXRegistryInterface" + +pub fun main(accountAddress: Address, idOrAlias: String, registryName: String): AnyStruct{FLIXRegistryInterface.InteractionTemplate}? { + let account = getAccount(accountAddress) + let registry = account.getCapability(FLIXRegistry.PublicPath(name: registryName)) + .borrow<&FLIXRegistry.Registry{FLIXRegistryInterface.Queryable}>() + ?? panic("Could not borrow a reference to the Registry") + + return registry.lookup(idOrAlias: idOrAlias) +} \ No newline at end of file diff --git a/registry/cadence/scripts/resolve.cdc b/registry/cadence/scripts/resolve.cdc new file mode 100644 index 0000000..f0215c0 --- /dev/null +++ b/registry/cadence/scripts/resolve.cdc @@ -0,0 +1,11 @@ +import "FLIXRegistry" +import "FLIXRegistryInterface" + +pub fun main(accountAddress: Address, cadenceBodyHash: String, registryName: String): AnyStruct{FLIXRegistryInterface.InteractionTemplate}? { + let account = getAccount(accountAddress) + let registry = account.getCapability(FLIXRegistry.PublicPath(name: registryName)) + .borrow<&FLIXRegistry.Registry{FLIXRegistryInterface.Queryable}>() + ?? panic("Could not borrow a reference to the Registry") + + return registry.resolve(cadenceBodyHash: cadenceBodyHash) +} \ No newline at end of file diff --git a/registry/cadence/test/flix_registry_test.cdc b/registry/cadence/test/flix_registry_test.cdc new file mode 100644 index 0000000..33b32cf --- /dev/null +++ b/registry/cadence/test/flix_registry_test.cdc @@ -0,0 +1,338 @@ +import Test +import BlockchainHelpers +import "FLIXSchema_draft" +import "FLIXRegistry" + +access(all) let REGISTRY_OWNER = Test.createAccount() +access(all) let TEMPLATE_ID = "aTestId" +access(all) let ALIAS = "anAlias" +access(all) let NEW_ALIAS = "aNewAlias" +access(all) let REGISTRY_NAME = "someName" +access(all) let FLIX_DATA: AnyStruct = "same data" +access(all) let CADENCE_BODY_HASH = "someHash" + +access(all) let CONTRACT_DEPLOYED_SNAPSHOT = "contract deployed" +access(all) let REGISTRY_CREATED_SNAPSHOT = "registry created" +access(all) let FLIX_PUBLISHED_SNAPSHOT = "flix published" + + +access(all) +fun setup() { + + let flixRegistryInterfaceErr = Test.deployContract( + name: "FLIXRegistryInterface", + path: "../contracts/flix_registry_interface.cdc", + arguments: [] + ) + Test.expect(flixRegistryInterfaceErr, Test.beNil()) + + let flixRegistryErr = Test.deployContract( + name: "FLIXRegistry", + path: "../contracts/flix_registry.cdc", + arguments: [] + ) + Test.expect(flixRegistryErr, Test.beNil()) + + let flixSchema_draftErr = Test.deployContract( + name: "FLIXSchema_draft", + path: "../contracts/flix_schema_draft.cdc", + arguments: [] + ) + Test.expect(flixSchema_draftErr, Test.beNil()) + Test.createSnapshot(name: CONTRACT_DEPLOYED_SNAPSHOT) + + let createTxResult = executeTransaction( + "../transactions/create_registry.cdc", + [REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(createTxResult, Test.beSucceeded()) + Test.createSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let publishTxResult = executeTransaction( + "../transactions/publish_flix.cdc", + [ALIAS, TEMPLATE_ID, FLIX_DATA, CADENCE_BODY_HASH, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(publishTxResult, Test.beSucceeded()) + Test.createSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) +} + +access(all) +fun testShouldEmitContractInitializedEvent() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let typ = Type() + Test.assertEqual(1, Test.eventsOfType(typ).length) +} + +access(all) +fun testShouldEmitRegistryCreatedEvent() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.RegistryCreated + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.name) +} + +access(all) +fun testShouldCreateRegistry() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let scriptResult = executeScript( + "../scripts/get_registry_size.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let registrySize = scriptResult.returnValue! as! Int + Test.assertEqual(0, registrySize) +} + +access(all) +fun testShouldEmitEventAfterFlixPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.Published + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.registryName) + Test.assertEqual(REGISTRY_OWNER.address, event.registryOwner) + Test.assertEqual(ALIAS, event.alias) + Test.assertEqual(TEMPLATE_ID, event.id) + Test.assertEqual(CADENCE_BODY_HASH, event.cadenceBodyHash) +} + +access(all) +fun testShouldContainFlixAfterPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let scriptResult = executeScript( + "../scripts/get_registry_size.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let registrySize = scriptResult.returnValue! as! Int + Test.assertEqual(1, registrySize) +} + +access(all) +fun testShouldLookupFlixAfterPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let lookupScriptResult = executeScript( + "../scripts/lookup.cdc", + [REGISTRY_OWNER.address, ALIAS, REGISTRY_NAME] + ) + + Test.expect(lookupScriptResult, Test.beSucceeded()) + + let flix = lookupScriptResult.returnValue! as! FLIXSchema_draft.FLIX + Test.assertEqual(TEMPLATE_ID, flix.id) + Test.assertEqual(FLIX_DATA, flix.getData()) + Test.assertEqual(CADENCE_BODY_HASH, flix.cadenceBodyHash) + Test.assertEqual(FLIXRegistry.FLIXStatus.active, flix.status) + Test.assertEqual("draft", flix.getVersion()) +} + +access(all) +fun testShouldResolveFlixAfterPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let resolveScriptResult = executeScript( + "../scripts/resolve.cdc", + [REGISTRY_OWNER.address, CADENCE_BODY_HASH, REGISTRY_NAME] + ) + + Test.expect(resolveScriptResult, Test.beSucceeded()) + + let resolvedFlix = resolveScriptResult.returnValue! as! FLIXSchema_draft.FLIX + Test.assertEqual(TEMPLATE_ID, resolvedFlix.id) + Test.assertEqual(FLIX_DATA, resolvedFlix.getData()) + Test.assertEqual(CADENCE_BODY_HASH, resolvedFlix.cadenceBodyHash) + Test.assertEqual(FLIXRegistry.FLIXStatus.active, resolvedFlix.status) +} + +access(all) +fun testShouldLinkAlias() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let txResult = executeTransaction( + "../transactions/link_alias.cdc", + [NEW_ALIAS, TEMPLATE_ID, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(txResult, Test.beSucceeded()) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.AliasLinked + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.registryName) + Test.assertEqual(REGISTRY_OWNER.address, event.registryOwner) + Test.assertEqual(NEW_ALIAS, event.alias) + Test.assertEqual(TEMPLATE_ID, event.id) + + let scriptResult = executeScript( + "../scripts/get_all_alias.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let aliases = scriptResult.returnValue! as! {String: String} + + Test.assertEqual(TEMPLATE_ID, aliases[ALIAS]!) + Test.assertEqual(TEMPLATE_ID, aliases[NEW_ALIAS]!) +} + +access(all) +fun testShouldUnlinkAlias() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let txResult = executeTransaction( + "../transactions/unlink_alias.cdc", + [ALIAS, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(txResult, Test.beSucceeded()) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.AliasUnlinked + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.registryName) + Test.assertEqual(REGISTRY_OWNER.address, event.registryOwner) + Test.assertEqual(ALIAS, event.alias) + + let scriptResult = executeScript( + "../scripts/get_all_alias.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let aliases = scriptResult.returnValue! as! {String: String} + + Test.assertEqual(nil, aliases[ALIAS]) + Test.assertEqual(TEMPLATE_ID, aliases[NEW_ALIAS]!) +} + +access(all) +fun testShouldDeprecateFlixWithTemplateId() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let lookupScriptResultBefore = executeScript( + "../scripts/lookup.cdc", + [REGISTRY_OWNER.address, TEMPLATE_ID, REGISTRY_NAME] + ) + let flixBefore = lookupScriptResultBefore.returnValue! as! FLIXSchema_draft.FLIX + Test.assertEqual(FLIXRegistry.FLIXStatus.active, flixBefore.status) + + let txResult = executeTransaction( + "../transactions/deprecate_flix.cdc", + [TEMPLATE_ID, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(txResult, Test.beSucceeded()) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.Deprecated + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.registryName) + Test.assertEqual(REGISTRY_OWNER.address, event.registryOwner) + Test.assertEqual(TEMPLATE_ID, event.id) + + let lookupScriptResultAfter = executeScript( + "../scripts/lookup.cdc", + [REGISTRY_OWNER.address, TEMPLATE_ID, REGISTRY_NAME] + ) + + Test.expect(lookupScriptResultAfter, Test.beSucceeded()) + + let flixAfter = lookupScriptResultAfter.returnValue! as! FLIXSchema_draft.FLIX + Test.assertEqual(FLIXRegistry.FLIXStatus.deprecated, flixAfter.status) +} + +access(all) +fun testShouldRemoveFlix() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let removeTxResult = executeTransaction( + "../transactions/remove_flix.cdc", + [TEMPLATE_ID, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(removeTxResult, Test.beSucceeded()) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.Removed + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.registryName) + Test.assertEqual(REGISTRY_OWNER.address, event.registryOwner) + Test.assertEqual(TEMPLATE_ID, event.id) + + let scriptResult = executeScript( + "../scripts/get_registry_size.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let registrySize = scriptResult.returnValue! as! Int + Test.assertEqual(0, registrySize) +} + +access(all) +fun testShouldNotEmitEventWhenRemovingNonexistentFlix() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let removeTxResult = executeTransaction( + "../transactions/remove_flix.cdc", + [TEMPLATE_ID, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(removeTxResult, Test.beSucceeded()) + + let typ = Type() + Test.assertEqual(0, Test.eventsOfType(typ).length) + + let scriptResult = executeScript( + "../scripts/get_registry_size.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let registrySize = scriptResult.returnValue! as! Int + Test.assertEqual(0, registrySize) +} + +access(all) +fun testShouldThrowExeptionWhenDeprecatingNonexistentFlix() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + Test.expectFailure(fun(): Void { + let txResult = executeTransaction( + "../transactions/deprecate_flix.cdc", + [TEMPLATE_ID, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(txResult, Test.beFailed()) + let err: Test.Error? = txResult.error + panic(err!.message) // to trick expectFaliure, so we can match on the substring of the actual error + }, errorMessageSubstring: "FLIX does not exist with the given id or alias: aTestId") + +} + +access(all) +fun testShouldCreatePublicPath() { + Test.assertEqual(/public/flix_test, FLIXRegistry.PublicPath(name: "test")) +} + +access(all) +fun testShouldCreateStoragePath() { + Test.assertEqual(/storage/flix_test, FLIXRegistry.StoragePath(name: "test")) +} \ No newline at end of file diff --git a/registry/cadence/test/flix_schema_v1_1_0_test.cdc b/registry/cadence/test/flix_schema_v1_1_0_test.cdc new file mode 100644 index 0000000..624819c --- /dev/null +++ b/registry/cadence/test/flix_schema_v1_1_0_test.cdc @@ -0,0 +1,365 @@ +import Test +import BlockchainHelpers +import "FLIXSchema_v1_1_0" +import "FLIXRegistry" + +access(all) let REGISTRY_OWNER = Test.createAccount() +access(all) let TEMPLATE_ID = "aTestId" +access(all) let ALIAS = "anAlias" +access(all) let NEW_ALIAS = "aNewAlias" +access(all) let REGISTRY_NAME = "someName" +access(all) let CADENCE_BODY_HASH = "someHash" +access(all) let SCHEMA_VERSION = "1.1.0" + +access(all) let CONTRACT_DEPLOYED_SNAPSHOT = "contract deployed" +access(all) let REGISTRY_CREATED_SNAPSHOT = "registry created" +access(all) let FLIX_PUBLISHED_SNAPSHOT = "flix published" + +access(all) +fun setup() { + + let flixRegistryInterfaceErr = Test.deployContract( + name: "FLIXRegistryInterface", + path: "../contracts/flix_registry_interface.cdc", + arguments: [] + ) + Test.expect(flixRegistryInterfaceErr, Test.beNil()) + + let flixRegistryErr = Test.deployContract( + name: "FLIXRegistry", + path: "../contracts/flix_registry.cdc", + arguments: [] + ) + Test.expect(flixRegistryErr, Test.beNil()) + + let flix_schema_v1_1_0 = Test.deployContract( + name: "FLIXSchema_v1_1_0", + path: "../contracts/flix_schema_v1_1_0.cdc", + arguments: [] + ) + Test.expect(flix_schema_v1_1_0, Test.beNil()) + Test.createSnapshot(name: CONTRACT_DEPLOYED_SNAPSHOT) + + let createTxResult = executeTransaction( + "../transactions/create_registry.cdc", + [REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(createTxResult, Test.beSucceeded()) + Test.createSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let flixData = FLIXSchema_v1_1_0.Data( + type: "transaction", + interface: "asadf23234...fas234234", + messages: [ + FLIXSchema_v1_1_0.Message( + key: "title", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "Transfer FLOW", + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "FLOW de transfert", + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "转移流程", + ) + ] + ), + FLIXSchema_v1_1_0.Message( + key: "description", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "Transfer {amount} FLOW to {to}", + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "Transférez {amount} FLOW à {to}", + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "将 {amount} FLOW 转移到 {to}", + ) + ] + ), + FLIXSchema_v1_1_0.Message( + key: "signer", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "Sign this message to transfer FLOW", + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "Signez ce message pour transférer FLOW.", + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "签署此消息以转移FLOW。", + ) + ] + ) + ], + cadence: FLIXSchema_v1_1_0.Cadence( + body: "import \"FlowToken\"\ntransaction(amount: UFix64, to: Address) {\n let vault: @FungibleToken.Vault\n prepare(signer: AuthAccount) {\n self.vault <- signer\n .borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n .withdraw(amount: amount)\n\n self.vault <- FungibleToken.getVault(signer)\n }\n execute {\n getAccount(to)\n .getCapability(/public/flowTokenReceiver)!\n .borrow<&{FungibleToken.Receiver}>()!\n .deposit(from: <-self.vault)\n }\n}", + networkPins: [ + FLIXSchema_v1_1_0.NetworkPin( + network: "mainnet", + pinSelf: "186e262ce6fe06b5075ec6569a0e5482a79c471881182612d8e4a665c2977f3e" + ), + FLIXSchema_v1_1_0.NetworkPin( + network: "testnet", + pinSelf: "f93977d7a297f559e97259cb2a95fed0f87cfeec46c5257a26adc26a260d6c4c" + ) + ] + ), + dependencies: [ + FLIXSchema_v1_1_0.Dependency( + contracts: [ + FLIXSchema_v1_1_0.Contract( + contract: "FlowToken", + networks: [ + FLIXSchema_v1_1_0.Network( + network: "mainnet", + address: "0x1654653399040a61", + dependencyPinBlockHeight: 10123123123, + dependencyPin: FLIXSchema_v1_1_0.DependencyPin( + pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b", + pinSelf: "38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb", + pinContractName: "FlowToken", + pinContractAddress: "0x1654653399040a61", + imports: [ + FLIXSchema_v1_1_0.Import( + pin: "b8a3ed26c222ed67016a28021d8fee5603b948533cbc992b3c90f71a61b2b312", + pinSelf: "7bc3056ba5d39d130f45411c2c05bb549db8ce727c11a1cb821136a621be27fb", + pinContractName: "FungibleToken", + pinContractAddress: "0xf233dcee88fe0abe", + imports: [] + ) + ] + ) + ), + FLIXSchema_v1_1_0.Network( + network: "testnet", + address: "0x7e60df042a9c0868", + dependencyPinBlockHeight: 10123123123, + dependencyPin: FLIXSchema_v1_1_0.DependencyPin( + pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b", + pinSelf: "38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb", + pinContractName: "FlowToken", + pinContractAddress: "0x7e60df042a9c0868", + imports: [ + FLIXSchema_v1_1_0.Import( + pin: "b8a3ed26c222ed67016a28021d8fee5603b948533cbc992b3c90f71a61b2b312", + pinSelf: "7bc3056ba5d39d130f45411c2c05bb549db8ce727c11a1cb821136a621be27fb", + pinContractName: "FungibleToken", + pinContractAddress: "0x9a0766d93b6608b7", + imports: [] + ) + ] + ) + ) + ] + ) + ] + ) + ], + parameters: [ + FLIXSchema_v1_1_0.Parameter( + label: "amount", + index: 0, + type: "UFix64", + messages: [ + FLIXSchema_v1_1_0.Message( + key: "title", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "Amount" + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "Montant" + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "数量" + ) + ] + ), + FLIXSchema_v1_1_0.Message( + key: "description", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "Amount of FLOW token to transfer" + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "Quantité de token FLOW à transférer" + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "要转移的 FLOW 代币数量" + ) + ]) + ], + balance: [ + FLIXSchema_v1_1_0.Balance( + network: "mainnet", + pin: "A.0xABC123DEF456.FlowToken" + ), + FLIXSchema_v1_1_0.Balance( + network: "testnet", + pin: "A.0xXYZ678DEF123.FlowToken" + ) + ] + ), + FLIXSchema_v1_1_0.Parameter( + label: "to", + index: 1, + type: "Address", + messages: [ + FLIXSchema_v1_1_0.Message( + key: "title", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "To" + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "Pour" + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "到" + ) + ] + ), + FLIXSchema_v1_1_0.Message( + key: "description", + i18n: [ + FLIXSchema_v1_1_0.I18n( + tag: "en-US", + translation: "Recipient of the FLOW token transfer" + ), + FLIXSchema_v1_1_0.I18n( + tag: "fr-FR", + translation: "Le compte vers lequel transférer les jetons FLOW" + ), + FLIXSchema_v1_1_0.I18n( + tag: "zh-CN", + translation: "将 FLOW 代币转移到的帐户" + ) + ] + ) + ], + balance: [] + ) + ] + ) + + let flix = FLIXSchema_v1_1_0.FLIX( + id: TEMPLATE_ID, + data: flixData, + cadenceBodyHash: CADENCE_BODY_HASH + ) + + let publishTxResult = executeTransaction( + "../transactions/publish_flix_v1_1_0.cdc", + [ALIAS, flix, REGISTRY_NAME], + REGISTRY_OWNER + ) + Test.expect(publishTxResult, Test.beSucceeded()) + Test.createSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) +} + +access(all) +fun testShouldEmitContractInitializedEvent() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let typ = Type() + Test.assertEqual(1, Test.eventsOfType(typ).length) +} + +access(all) +fun testShouldEmitRegistryCreatedEvent() { + Test.loadSnapshot(name: REGISTRY_CREATED_SNAPSHOT) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.RegistryCreated + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.name) +} + +access(all) +fun testShouldEmitEventAfterFlixPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let typ = Type() + let events = Test.eventsOfType(typ) + let event = events[0] as! FLIXRegistry.Published + Test.assertEqual(1, events.length) + Test.assertEqual(REGISTRY_NAME, event.registryName) + Test.assertEqual(REGISTRY_OWNER.address, event.registryOwner) + Test.assertEqual(ALIAS, event.alias) + Test.assertEqual(TEMPLATE_ID, event.id) + Test.assertEqual(CADENCE_BODY_HASH, event.cadenceBodyHash) +} + +access(all) +fun testShouldContainFlixAfterPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let scriptResult = executeScript( + "../scripts/get_registry_size.cdc", + [REGISTRY_OWNER.address, REGISTRY_NAME] + ) + Test.expect(scriptResult, Test.beSucceeded()) + + let registrySize = scriptResult.returnValue! as! Int + Test.assertEqual(1, registrySize) +} + +access(all) +fun testShouldLookupFlixAfterPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let lookupScriptResult = executeScript( + "../scripts/lookup.cdc", + [REGISTRY_OWNER.address, ALIAS, REGISTRY_NAME] + ) + + Test.expect(lookupScriptResult, Test.beSucceeded()) + + let flix = lookupScriptResult.returnValue! as! FLIXSchema_v1_1_0.FLIX + Test.assertEqual(TEMPLATE_ID, flix.id) + Test.assertEqual("transaction", flix.getData().type) + Test.assertEqual(CADENCE_BODY_HASH, flix.cadenceBodyHash) + Test.assertEqual(FLIXRegistry.FLIXStatus.active, flix.status) + Test.assertEqual(SCHEMA_VERSION, flix.getVersion()) +} + +access(all) +fun testShouldResolveFlixAfterPublished() { + Test.loadSnapshot(name: FLIX_PUBLISHED_SNAPSHOT) + + let resolveScriptResult = executeScript( + "../scripts/resolve.cdc", + [REGISTRY_OWNER.address, CADENCE_BODY_HASH, REGISTRY_NAME] + ) + + Test.expect(resolveScriptResult, Test.beSucceeded()) + + let resolvedFlix = resolveScriptResult.returnValue! as! FLIXSchema_v1_1_0.FLIX + Test.assertEqual(TEMPLATE_ID, resolvedFlix.id) + Test.assertEqual("transaction", resolvedFlix.getData().type) + Test.assertEqual(CADENCE_BODY_HASH, resolvedFlix.cadenceBodyHash) + Test.assertEqual(FLIXRegistry.FLIXStatus.active, resolvedFlix.status) +} diff --git a/registry/cadence/transactions/create_registry.cdc b/registry/cadence/transactions/create_registry.cdc new file mode 100644 index 0000000..f1f6493 --- /dev/null +++ b/registry/cadence/transactions/create_registry.cdc @@ -0,0 +1,17 @@ +import "FLIXRegistry" +import "FLIXRegistryInterface" + +transaction(name: String) { + + prepare(signer: AuthAccount) { + // Check if the account already has a Registry + if signer.borrow<&FLIXRegistry.Registry>(from: FLIXRegistry.StoragePath(name: name)) == nil { + // Create a new Registry resource + let registry <- FLIXRegistry.createRegistry(name: name) + + // Save it with restricted access + signer.save(<-registry, to: FLIXRegistry.StoragePath(name: name)) + signer.link<&FLIXRegistry.Registry{FLIXRegistryInterface.Queryable}>(FLIXRegistry.PublicPath(name: name), target: FLIXRegistry.StoragePath(name: name)) + } + } +} \ No newline at end of file diff --git a/registry/cadence/transactions/deprecate_flix.cdc b/registry/cadence/transactions/deprecate_flix.cdc new file mode 100644 index 0000000..2697e42 --- /dev/null +++ b/registry/cadence/transactions/deprecate_flix.cdc @@ -0,0 +1,11 @@ +import "FLIXRegistry" + +transaction(idOrAlias: String, registryName: String) { + + prepare(signer: AuthAccount) { + let registry = signer.borrow<&FLIXRegistry.Registry>(from: FLIXRegistry.StoragePath(name: registryName)) + ?? panic("Could not borrow a reference to the Registry") + + registry.deprecate(idOrAlias: idOrAlias) + } +} diff --git a/registry/cadence/transactions/link_alias.cdc b/registry/cadence/transactions/link_alias.cdc new file mode 100644 index 0000000..5ecdd97 --- /dev/null +++ b/registry/cadence/transactions/link_alias.cdc @@ -0,0 +1,11 @@ +import "FLIXRegistry" + +transaction(alias: String, templateId: String, registryName: String) { + + prepare(signer: AuthAccount) { + let registry = signer.borrow<&FLIXRegistry.Registry>(from: FLIXRegistry.StoragePath(name: registryName)) + ?? panic("Could not borrow a reference to the Registry") + + registry.link(alias: alias, id: templateId) + } +} \ No newline at end of file diff --git a/registry/cadence/transactions/publish_flix.cdc b/registry/cadence/transactions/publish_flix.cdc new file mode 100644 index 0000000..53a573f --- /dev/null +++ b/registry/cadence/transactions/publish_flix.cdc @@ -0,0 +1,13 @@ +import "FLIXRegistry" +import "FLIXSchema_draft" + +transaction(alias: String, templateId: String, jsonBody: String, cadenceBodyHash: String, registryName: String) { + + prepare(signer: AuthAccount) { + let registry = signer.borrow<&FLIXRegistry.Registry>(from: FLIXRegistry.StoragePath(name: registryName)) + ?? panic("Could not borrow a reference to the Registry") + + let newFlix = FLIXSchema_draft.FLIX(templateId: templateId, jsonBody: jsonBody, cadenceBodyHash: cadenceBodyHash) + registry.publish(alias: alias, flix: newFlix) + } +} \ No newline at end of file diff --git a/registry/cadence/transactions/publish_flix_v1_1_0.cdc b/registry/cadence/transactions/publish_flix_v1_1_0.cdc new file mode 100644 index 0000000..69aa6ec --- /dev/null +++ b/registry/cadence/transactions/publish_flix_v1_1_0.cdc @@ -0,0 +1,12 @@ +import "FLIXRegistry" +import "FLIXSchema_v1_1_0" + +transaction(alias: String, flix: FLIXSchema_v1_1_0.FLIX, registryName: String) { + + prepare(signer: AuthAccount) { + let registry = signer.borrow<&FLIXRegistry.Registry>(from: FLIXRegistry.StoragePath(name: registryName)) + ?? panic("Could not borrow a reference to the Registry") + registry.publish(alias: alias, flix: flix) + } +} + diff --git a/registry/cadence/transactions/remove_flix.cdc b/registry/cadence/transactions/remove_flix.cdc new file mode 100644 index 0000000..13963ed --- /dev/null +++ b/registry/cadence/transactions/remove_flix.cdc @@ -0,0 +1,14 @@ +import "FLIXRegistry" +import "FLIXRegistryInterface" + +transaction(id: String, registryName: String) { + + prepare(signer: AuthAccount) { + // Borrow a reference to the Registry with removal capability + let registry = signer.borrow<&FLIXRegistry.Registry{FLIXRegistryInterface.Removable}>(from: FLIXRegistry.StoragePath(name: registryName)) + ?? panic("Could not borrow a reference to the Registry") + + // Remove the FLIX item using the provided id + registry.remove(id: id) + } +} diff --git a/registry/cadence/transactions/unlink_alias.cdc b/registry/cadence/transactions/unlink_alias.cdc new file mode 100644 index 0000000..b20b7a8 --- /dev/null +++ b/registry/cadence/transactions/unlink_alias.cdc @@ -0,0 +1,11 @@ +import "FLIXRegistry" + +transaction(alias: String, registryName: String) { + + prepare(signer: AuthAccount) { + let registry = signer.borrow<&FLIXRegistry.Registry>(from: FLIXRegistry.StoragePath(name: registryName)) + ?? panic("Could not borrow a reference to the Registry") + + registry.unlink(alias: alias) + } +} \ No newline at end of file diff --git a/registry/flow.json b/registry/flow.json new file mode 100644 index 0000000..101c8a0 --- /dev/null +++ b/registry/flow.json @@ -0,0 +1,53 @@ +{ + "contracts": { + "FLIXRegistry": { + "source": "cadence/contracts/flix_registry.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testing": "0x0000000000000007" + } + }, + "FLIXRegistryInterface": { + "source": "cadence/contracts/flix_registry_interface.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testing": "0x0000000000000007" + } + }, + "FLIXSchema_draft": { + "source": "cadence/contracts/flix_schema_draft.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testing": "0x0000000000000007" + } + }, + "FLIXSchema_v1_1_0": { + "source": "cadence/contracts/flix_schema_v1_1_0.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", + "testing": "0x0000000000000007" + } + } + }, + "networks": { + "testing": "127.0.0.1:3569", + "emulator": "127.0.0.1:3569", + "mainnet": "access.mainnet.nodes.onflow.org:9000", + "testnet": "access.devnet.nodes.onflow.org:9000" + }, + "deployments" : { + "emulator" : { + "emulator-account": ["FLIXRegistry"] + } + }, + "accounts": { + "emulator-account": { + "address": "f8d6e0586b0a20c7", + "key": "6d12eebfef9866c9b6fa92b97c6e705c26a1785b1e7944da701fc545a51d4673" + }, + "emulator-flix": { + "address": "179b6b1cb6755e31", + "key": "573b0db3fe91458e2aceefb8318d6daf3aee2af986a850cbf27a8ffff8a4ef9f" + } + } +} From e516d56cd89730286c04b8b6b5553028972841b4 Mon Sep 17 00:00:00 2001 From: wfalcon0x Date: Tue, 20 Feb 2024 18:27:00 +0000 Subject: [PATCH 2/3] convert FLIXStatus enum to String --- registry/cadence/contracts/flix_registry.cdc | 12 +----------- .../cadence/contracts/flix_registry_interface.cdc | 12 +----------- registry/cadence/contracts/flix_schema_draft.cdc | 4 ++-- registry/cadence/contracts/flix_schema_v1_1_0.cdc | 6 +++--- registry/cadence/test/flix_registry_test.cdc | 8 ++++---- registry/cadence/test/flix_schema_v1_1_0_test.cdc | 4 ++-- 6 files changed, 13 insertions(+), 33 deletions(-) diff --git a/registry/cadence/contracts/flix_registry.cdc b/registry/cadence/contracts/flix_registry.cdc index 121040c..fec4d41 100644 --- a/registry/cadence/contracts/flix_registry.cdc +++ b/registry/cadence/contracts/flix_registry.cdc @@ -24,16 +24,6 @@ contract FLIXRegistry: FLIXRegistryInterface { access(all) event AliasUnlinked(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String) - access(all) - enum FLIXStatus: UInt8 { - - access(all) - case active - - access(all) - case deprecated - } - access(all) resource Registry: FLIXRegistryInterface.Queryable, FLIXRegistryInterface.Removable, FLIXRegistryInterface.Admin { @@ -83,7 +73,7 @@ contract FLIXRegistry: FLIXRegistryInterface { access(all) fun deprecate(idOrAlias: String) { var flix = self.lookup(idOrAlias: idOrAlias) ?? panic("FLIX does not exist with the given id or alias: ".concat(idOrAlias)) - flix.status = FLIXStatus.deprecated + flix.status = "deprecated" self.flixes[flix.getId()] = flix emit Deprecated(registryOwner: self.owner!.address, registryName: self.name, registryUuid: self.uuid, id: flix.getId()) } diff --git a/registry/cadence/contracts/flix_registry_interface.cdc b/registry/cadence/contracts/flix_registry_interface.cdc index 672bf41..fad23be 100644 --- a/registry/cadence/contracts/flix_registry_interface.cdc +++ b/registry/cadence/contracts/flix_registry_interface.cdc @@ -22,16 +22,6 @@ contract interface FLIXRegistryInterface { access(all) event AliasUnlinked(registryOwner: Address, registryName: String, registryUuid: UInt64, alias: String) - access(all) - enum FLIXStatus: UInt8 { - - access(all) - case active - - access(all) - case deprecated - } - access(all) struct interface InteractionTemplate { access(all) @@ -44,7 +34,7 @@ contract interface FLIXRegistryInterface { fun getCadenceBodyHash(): String pub(set) - var status: FLIXStatus + var status: String access(all) fun getData(): AnyStruct diff --git a/registry/cadence/contracts/flix_schema_draft.cdc b/registry/cadence/contracts/flix_schema_draft.cdc index 12349ab..210329c 100644 --- a/registry/cadence/contracts/flix_schema_draft.cdc +++ b/registry/cadence/contracts/flix_schema_draft.cdc @@ -36,13 +36,13 @@ contract FLIXSchema_draft { } pub(set) - var status: FLIXRegistryInterface.FLIXStatus + var status: String init(id: String, data: AnyStruct, cadenceBodyHash: String) { self.id = id self.data = data self.cadenceBodyHash = cadenceBodyHash - self.status = FLIXRegistry.FLIXStatus.active + self.status = "active" } } diff --git a/registry/cadence/contracts/flix_schema_v1_1_0.cdc b/registry/cadence/contracts/flix_schema_v1_1_0.cdc index 532cb0f..b7c2ee1 100644 --- a/registry/cadence/contracts/flix_schema_v1_1_0.cdc +++ b/registry/cadence/contracts/flix_schema_v1_1_0.cdc @@ -36,18 +36,18 @@ contract FLIXSchema_v1_1_0 { } access(all) - fun getStatus(): FLIXRegistryInterface.FLIXStatus { + fun getStatus(): String { return self.status } pub(set) - var status: FLIXRegistryInterface.FLIXStatus + var status: String init(id: String, data: Data, cadenceBodyHash: String) { self.id = id self.data = data self.cadenceBodyHash = cadenceBodyHash - self.status = FLIXRegistry.FLIXStatus.active + self.status = "active" } } diff --git a/registry/cadence/test/flix_registry_test.cdc b/registry/cadence/test/flix_registry_test.cdc index 33b32cf..4be811c 100644 --- a/registry/cadence/test/flix_registry_test.cdc +++ b/registry/cadence/test/flix_registry_test.cdc @@ -135,7 +135,7 @@ fun testShouldLookupFlixAfterPublished() { Test.assertEqual(TEMPLATE_ID, flix.id) Test.assertEqual(FLIX_DATA, flix.getData()) Test.assertEqual(CADENCE_BODY_HASH, flix.cadenceBodyHash) - Test.assertEqual(FLIXRegistry.FLIXStatus.active, flix.status) + Test.assertEqual("active", flix.status) Test.assertEqual("draft", flix.getVersion()) } @@ -154,7 +154,7 @@ fun testShouldResolveFlixAfterPublished() { Test.assertEqual(TEMPLATE_ID, resolvedFlix.id) Test.assertEqual(FLIX_DATA, resolvedFlix.getData()) Test.assertEqual(CADENCE_BODY_HASH, resolvedFlix.cadenceBodyHash) - Test.assertEqual(FLIXRegistry.FLIXStatus.active, resolvedFlix.status) + Test.assertEqual("active", resolvedFlix.status) } access(all) @@ -229,7 +229,7 @@ fun testShouldDeprecateFlixWithTemplateId() { [REGISTRY_OWNER.address, TEMPLATE_ID, REGISTRY_NAME] ) let flixBefore = lookupScriptResultBefore.returnValue! as! FLIXSchema_draft.FLIX - Test.assertEqual(FLIXRegistry.FLIXStatus.active, flixBefore.status) + Test.assertEqual("active", flixBefore.status) let txResult = executeTransaction( "../transactions/deprecate_flix.cdc", @@ -254,7 +254,7 @@ fun testShouldDeprecateFlixWithTemplateId() { Test.expect(lookupScriptResultAfter, Test.beSucceeded()) let flixAfter = lookupScriptResultAfter.returnValue! as! FLIXSchema_draft.FLIX - Test.assertEqual(FLIXRegistry.FLIXStatus.deprecated, flixAfter.status) + Test.assertEqual("deprecated", flixAfter.status) } access(all) diff --git a/registry/cadence/test/flix_schema_v1_1_0_test.cdc b/registry/cadence/test/flix_schema_v1_1_0_test.cdc index 624819c..69cbab0 100644 --- a/registry/cadence/test/flix_schema_v1_1_0_test.cdc +++ b/registry/cadence/test/flix_schema_v1_1_0_test.cdc @@ -342,7 +342,7 @@ fun testShouldLookupFlixAfterPublished() { Test.assertEqual(TEMPLATE_ID, flix.id) Test.assertEqual("transaction", flix.getData().type) Test.assertEqual(CADENCE_BODY_HASH, flix.cadenceBodyHash) - Test.assertEqual(FLIXRegistry.FLIXStatus.active, flix.status) + Test.assertEqual("active", flix.status) Test.assertEqual(SCHEMA_VERSION, flix.getVersion()) } @@ -361,5 +361,5 @@ fun testShouldResolveFlixAfterPublished() { Test.assertEqual(TEMPLATE_ID, resolvedFlix.id) Test.assertEqual("transaction", resolvedFlix.getData().type) Test.assertEqual(CADENCE_BODY_HASH, resolvedFlix.cadenceBodyHash) - Test.assertEqual(FLIXRegistry.FLIXStatus.active, resolvedFlix.status) + Test.assertEqual("active", resolvedFlix.status) } From d36939d3fbb076289691d9dc4a0bdc47481846fa Mon Sep 17 00:00:00 2001 From: wfalcon0x Date: Mon, 26 Feb 2024 14:35:38 -0700 Subject: [PATCH 3/3] add configuration for testnet deployment --- registry/flow.json | 120 +++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/registry/flow.json b/registry/flow.json index 101c8a0..f4f4bd8 100644 --- a/registry/flow.json +++ b/registry/flow.json @@ -1,53 +1,69 @@ { - "contracts": { - "FLIXRegistry": { - "source": "cadence/contracts/flix_registry.cdc", - "aliases": { - "emulator": "0xf8d6e0586b0a20c7", - "testing": "0x0000000000000007" - } - }, - "FLIXRegistryInterface": { - "source": "cadence/contracts/flix_registry_interface.cdc", - "aliases": { - "emulator": "0xf8d6e0586b0a20c7", - "testing": "0x0000000000000007" - } - }, - "FLIXSchema_draft": { - "source": "cadence/contracts/flix_schema_draft.cdc", - "aliases": { - "emulator": "0xf8d6e0586b0a20c7", - "testing": "0x0000000000000007" - } - }, - "FLIXSchema_v1_1_0": { - "source": "cadence/contracts/flix_schema_v1_1_0.cdc", - "aliases": { - "emulator": "0xf8d6e0586b0a20c7", - "testing": "0x0000000000000007" - } - } - }, - "networks": { - "testing": "127.0.0.1:3569", - "emulator": "127.0.0.1:3569", - "mainnet": "access.mainnet.nodes.onflow.org:9000", - "testnet": "access.devnet.nodes.onflow.org:9000" - }, - "deployments" : { - "emulator" : { - "emulator-account": ["FLIXRegistry"] - } - }, - "accounts": { - "emulator-account": { - "address": "f8d6e0586b0a20c7", - "key": "6d12eebfef9866c9b6fa92b97c6e705c26a1785b1e7944da701fc545a51d4673" - }, - "emulator-flix": { - "address": "179b6b1cb6755e31", - "key": "573b0db3fe91458e2aceefb8318d6daf3aee2af986a850cbf27a8ffff8a4ef9f" - } - } -} + "contracts": { + "FLIXRegistry": { + "source": "cadence/contracts/flix_registry.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + }, + "FLIXRegistryInterface": { + "source": "cadence/contracts/flix_registry_interface.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + }, + "FLIXSchema_draft": { + "source": "cadence/contracts/flix_schema_draft.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + }, + "FLIXSchema_v1_1_0": { + "source": "cadence/contracts/flix_schema_v1_1_0.cdc", + "aliases": { + "emulator": "f8d6e0586b0a20c7", + "testing": "0000000000000007" + } + } + }, + "networks": { + "emulator": "127.0.0.1:3569", + "mainnet": "access.mainnet.nodes.onflow.org:9000", + "testing": "127.0.0.1:3569", + "testnet": "access.devnet.nodes.onflow.org:9000" + }, + "accounts": { + "emulator-account": { + "address": "f8d6e0586b0a20c7", + "key": "6d12eebfef9866c9b6fa92b97c6e705c26a1785b1e7944da701fc545a51d4673" + }, + "emulator-flix": { + "address": "179b6b1cb6755e31", + "key": "573b0db3fe91458e2aceefb8318d6daf3aee2af986a850cbf27a8ffff8a4ef9f" + }, + "testnet-account": { + "address": "0e2b3f46c2f076a0", + "key": { + "type": "file", + "location": "testnet-account.pkey" + } + } + }, + "deployments": { + "emulator": { + "emulator-account": [ + "FLIXRegistry" + ] + }, + "testnet": { + "testnet-account" : [ + "FLIXRegistryInterface", + "FLIXRegistry", + "FLIXSchema_v1_1_0" + ] + } + } +} \ No newline at end of file