Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for running cadence from 1.1.0 flix json files #1811

Merged
merged 6 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slimy-buses-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@onflow/fcl": patch
bthaile marked this conversation as resolved.
Show resolved Hide resolved
---

Add initial support to execute FLIX 1.1.0 for beta testing
19 changes: 19 additions & 0 deletions packages/fcl/src/exec/utils/derive-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ export async function deriveDependencies(opts = {}) {

return derivedDependencies

case "1.1.0":
template?.data?.dependencies?.forEach(dependency => {
dependency.contracts.forEach(contract => {
const contractName = contract.contract
contract.networks.forEach(net => {
if (net.network === network) {
derivedDependencies[contractName] = withPrefix(net?.address)
}
})

invariant(
derivedDependencies[contractName],
`networkAddress -- Could not find contracts Network Address: ${network} ${contractName}`
)
})
})

return derivedDependencies

default:
throw new Error(
"FCL configureDependencies Error: Unsupported template version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,48 @@ export function deriveCadenceByNetwork({network, template}) {

return [dependencyPlaceholder, dependencyContractForNetwork.address]
}
)

)
return networkDependencies.reduce((cadence, [placeholder, address]) => {
const regex = new RegExp("(\\b" + placeholder + "\\b)", "g")
return cadence.replace(regex, address)
}, template.data.cadence)

case "1.1.0":
// get network dependencies from template dependencies, use new string import format
const networkDeps = {}

template?.data?.dependencies.forEach(dependency => {
dependency.contracts.forEach(contract => {
const contractName = contract.contract
contract.networks.forEach(net => {
if (net.network === network) {
networkDeps[contractName] = net.address
}
})

invariant(
networkDeps[contractName],
`networkAddress -- Could not find contracts Network Address: ${network} ${contractName}`
)
})
})

invariant(
Object.keys(networkDeps).length === template?.data?.dependencies.length,
`networkDeps -- Could not find contracts for import dependencies: ${networkDeps}`
)

invariant(
Object.keys(networkDeps).length === Object.values(networkDeps).length,
`networkDeps -- Could not find all addresses for network ${network} dependencies: ${networkDeps}`
)

return Object.keys(networkDeps).reduce((cadence, contractName) => {
const test = new RegExp(`\\bimport\\b\\s*\\\"${contractName}\\\"`, "g")
return cadence.replace(test, `import ${contractName} from ${networkDeps[contractName]}`)
}, template.data.cadence.body)

default:
throw new Error(
"deriveCadenceByNetwork Error: Unsupported template version"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {deriveCadenceByNetwork} from "./derive-cadence-by-network.js"

describe("Derive cadence by network", () => {
describe("Derive cadence by network 1.0.0", () => {
let template = {
f_type: "InteractionTemplate",
f_version: "1.0.0",
Expand Down Expand Up @@ -52,3 +52,259 @@ describe("Derive cadence by network", () => {
).toThrow(Error)
})
})

describe("Derive cadence by network 1.1.0 single import", () => {
let templatev11 = {
f_type: "InteractionTemplate",
f_version: "1.1.0",
id: "a2b2d73def...aabc5472d2",
data: {
type: "transaction",
interface: "asadf23234...fas234234",
messages: [],
cadence: {
body: "import \"FlowToken\"\n transaction(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 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 }",
pins: [
{
network: "mainnet",
pin: "186e262ce6fe06b5075ec6569a0e5482a79c471881182612d8e4a665c2977f3e",
},
{
network: "testnet",
pin: "f93977d7a297f559e97259cb2a95fed0f87cfeec46c5257a26adc26a260d6c4c",
},
],
},
dependencies: [
{
contracts: [
{
contract: "FlowToken",
networks: [
{
network: "mainnet",
address: "0x1654653399040a61",
dependency_pin_block_height: 10123123123,
dependency_pin: {
pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b",
pin_self:
"38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb",
pin_contract_name: "FlowToken",
imports: [
{
pin: "b8a3ed26c222ed67016a28021d8fee5603b948533cbc992b3c90f71a61b2b312",
pin_self:
"7bc3056ba5d39d130f45411c2c05bb549db8ce727c11a1cb821136a621be27fb",
pin_contract_name: "FungibleToken",
pin_contract_address: "0xf233dcee88fe0abe",
imports: [],
},
],
},
},
{
network: "testnet",
address: "0x7e60df042a9c0868",
dependency_pin_block_height: 10123123123,
dependency_pin: {
pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b",
pin_self:
"38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb",
pin_contract_name: "FlowToken",
pin_contract_address: "0x7e60df042a9c0868",
imports: [],
},
},
],
},
],
},
],
parameters: [
{
label: "amount",
index: 0,
type: "UFix64",
messages: [],
balance: "FlowToken",
},
{
label: "to",
index: 1,
type: "Address",
messages: [],
},
],
},
}

const mainnetAddressReplaced = "import FlowToken from 0x1654653399040a61\n transaction(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 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 }"
test("1.1.0 derives cadence correctly for a given mainnet", async () => {
let cadence = deriveCadenceByNetwork({
network: "mainnet",
template: templatev11,
})

expect(cadence).toEqual(mainnetAddressReplaced)


})

const testnetAddressReplaced = "import FlowToken from 0x7e60df042a9c0868\n transaction(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 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 }"
test("1.1.0 derives cadence correctly for a given testnet", async () => {
let cadence = deriveCadenceByNetwork({
network: "testnet",
template: templatev11,
})

expect(cadence).toEqual(testnetAddressReplaced)
})

test("It fails to derive cadence for unknown network", async () => {
expect(() =>
deriveCadenceByNetwork({
network: "randomnet",
templatev11,
})
).toThrow(Error)
})
})


describe("Derive cadence by network 1.1.0 multiple import", () => {
let templatev11 = {
f_type: "InteractionTemplate",
f_version: "1.1.0",
id: "a2b2d73def...aabc5472d2",
data: {
type: "transaction",
interface: "asadf23234...fas234234",
messages: [],
cadence: {
body: "import \"FlowToken\"\n import \"FungibleToken\"\n transaction(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 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 }",
pins: [
{
network: "mainnet",
pin: "186e262ce6fe06b5075ec6569a0e5482a79c471881182612d8e4a665c2977f3e",
},
{
network: "testnet",
pin: "f93977d7a297f559e97259cb2a95fed0f87cfeec46c5257a26adc26a260d6c4c",
},
],
},
dependencies: [
{
contracts: [
{
contract: "FlowToken",
networks: [
{
network: "mainnet",
address: "0x1654653399040a61",
dependency_pin_block_height: 10123123123,
dependency_pin: {
pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b",
pin_self:
"38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb",
pin_contract_name: "FlowToken",
imports: [],
},
},
{
network: "testnet",
address: "0x7e60df042a9c0868",
dependency_pin_block_height: 10123123123,
dependency_pin: {
pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b",
pin_self:
"38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb",
pin_contract_name: "FlowToken",
pin_contract_address: "0x7e60df042a9c0868",
imports: [],
},
},
],
},
{
contract: "FungibleToken",
networks: [
{
network: "mainnet",
address: "0xf233dcee88fe0abe",
dependency_pin_block_height: 10123123123,
dependency_pin: {
pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b",
pin_self:
"38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb",
pin_contract_name: "FlowToken",
imports: [],
},
},
{
network: "testnet",
address: "0x11111111111",
dependency_pin_block_height: 10123123123,
dependency_pin: {
pin: "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b",
pin_self:
"38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb",
pin_contract_name: "FlowToken",
pin_contract_address: "0x7e60df042a9c0868",
imports: [],
},
},
],
},
],
},
],
parameters: [
{
label: "amount",
index: 0,
type: "UFix64",
messages: [],
balance: "FlowToken",
},
{
label: "to",
index: 1,
type: "Address",
messages: [],
},
],
},
}

const mainnetAddressReplaced = "import FlowToken from 0x1654653399040a61\n import FungibleToken from 0xf233dcee88fe0abe\n transaction(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 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 }"
test("1.1.0 multiple imports derives cadence correctly for a given mainnet", async () => {
let cadence = deriveCadenceByNetwork({
network: "mainnet",
template: templatev11,
})

expect(cadence).toEqual(mainnetAddressReplaced)


})

const testnetAddressReplaced = "import FlowToken from 0x7e60df042a9c0868\n import FungibleToken from 0x11111111111\n transaction(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 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 }"
test("1.1.0 multiple imports derives cadence correctly for a given testnet", async () => {
let cadence = deriveCadenceByNetwork({
network: "testnet",
template: templatev11,
})

expect(cadence).toEqual(testnetAddressReplaced)
})

test("1.1.0 multiple imports fails to derive cadence for unknown network", async () => {
expect(() =>
deriveCadenceByNetwork({
network: "randomnet",
templatev11,
})
).toThrow(Error)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export function normalizeInteractionTemplate(template) {
switch (template["f_version"]) {
case "1.0.0":
return template

case "1.1.0":
return template
default:
throw new Error(
"normalizeInteractionTemplate Error: Invalid InteractionTemplate"
Expand Down
Loading