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

Adds metadata views to FlowToken and removes init parameter #370

Merged
merged 10 commits into from
Jul 13, 2023
Merged
69 changes: 64 additions & 5 deletions contracts/FlowToken.cdc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import FungibleToken from 0xFUNGIBLETOKENADDRESS
import FungibleTokenMetadataViews from "./FungibleTokenMetadataViews.cdc"

pub contract FlowToken: FungibleToken {
joshuahannan marked this conversation as resolved.
Show resolved Hide resolved

Expand Down Expand Up @@ -83,6 +84,64 @@ pub contract FlowToken: FungibleToken {
FlowToken.totalSupply = FlowToken.totalSupply - self.balance
}
}

/// Get all the Metadata Views implemented by FlowToken
///
/// @return An array of Types defining the implemented views. This value will be used by
/// developers to know which parameter to pass to the resolveView() method.
///
pub fun getViews(): [Type]{
joshuahannan marked this conversation as resolved.
Show resolved Hide resolved
return [Type<FungibleTokenMetadataViews.FTView>(),
Type<FungibleTokenMetadataViews.FTDisplay>(),
Type<FungibleTokenMetadataViews.FTVaultData>()]
}

/// Get a Metadata View from FlowToken
///
/// @param view: The Type of the desired view.
/// @return A structure representing the requested view.
///
pub fun resolveView(_ view: Type): AnyStruct? {
switch view {
case Type<FungibleTokenMetadataViews.FTView>():
return FungibleTokenMetadataViews.FTView(
ftDisplay: self.resolveView(Type<FungibleTokenMetadataViews.FTDisplay>()) as! FungibleTokenMetadataViews.FTDisplay?,
ftVaultData: self.resolveView(Type<FungibleTokenMetadataViews.FTVaultData>()) as! FungibleTokenMetadataViews.FTVaultData?
)
case Type<FungibleTokenMetadataViews.FTDisplay>():
let media = MetadataViews.Media(
file: MetadataViews.HTTPFile(
url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know where this is hosted? It'd be great to get this pinned in IPFS or some other Web3 native solution.

Copy link
Member Author

@joshuahannan joshuahannan Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure actually. yeah IPFS would be great. I'd like to get this merged first though and then we can start looking into it in the future

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might just store it on chain in xml format since it is small

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anybody have any ideas about which metadata view would be the best to use for storing an entire XML file? This one would only be about 2KB so we can probably just store it all on chain, but I don't know which one to use or if we have to create a new view for it

Copy link
Contributor

@bluesign bluesign Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I would just save the entire XML file as a String in the URI field?

Copy link

@austinkline austinkline Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So long as you encode the start with the right preface that should work, I think. Only returning the string won't tell platforms how to interpret the data being returned

Copy link
Contributor

@bluesign bluesign Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will be:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNDAgMTAwIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6IzIzMWYyMDt9LmNscy0ye2ZpbGw6IzAwZWY4Yjt9LmNscy0ze2ZpbGw6I2ZmZjt9LmNscy00e2ZpbGw6IzE2ZmY5OTt9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkxheWVyXzIiIGRhdGEtbmFtZT0iTGF5ZXIgMiI+PGcgaWQ9IkxheWVyXzEtMiIgZGF0YS1uYW1lPSJMYXllciAxIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMzcuNjgsNDkuODhoLTYuNDVWNzMuOTNoLTlWNDkuODhoLTQuNjVWNDIuMTdoNC42NXYtM2MwLTcuNzcsNC44NS0xMS43NiwxMi4yMi0xMS43NmExNS42OCwxNS42OCwwLDAsMSwzLjM5LjR2OWE4LjM1LDguMzUsMCwwLDAtMy4wNS0uNiwzLjI4LDMuMjgsMCwwLDAtMy41MywzLjUydjIuMzloNi40NVptMTMuNTUsMjQuMDVoLTkuMVYyOC4wOWg5LjFaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcxLjQzLDQwLjE4YTE3LjI0LDE3LjI0LDAsMSwxLTE3LjIxLDE3LjIxQTE3LDE3LDAsMCwxLDE3MS40Myw0MC4xOFptMCwyNS42NWM0LjY1LDAsOC0zLjg2LDgtOC40NGE4LDgsMCwwLDAtOC04LjM3LDguNDEsOC40MSwwLDAsMCwwLDE2LjgxWiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5OC4xNCw0MC44NWw1Ljg1LDIyLDUuODUtMTcuNDgtMS42LTQuNTFoOWw3LjcxLDIyLDUuNzEtMjJIMjQwbC05LjgzLDMzLjA4aC05LjQ0TDIxNC4xNSw1NS44LDIwOCw3My45M2gtOS41bC05Ljc3LTMzLjA4WiIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNTAiIGN5PSI1MCIgcj0iNTAiLz48cmVjdCBjbGFzcz0iY2xzLTMiIHg9IjU3LjgyIiB5PSI0Mi4xOCIgd2lkdGg9IjE0LjEyIiBoZWlnaHQ9IjE0LjEyIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNNDMuNzEsNjEuNTlhNS4zLDUuMywwLDEsMS01LjMtNS4zaDUuM1Y0Mi4xOGgtNS4zQTE5LjQxLDE5LjQxLDAsMSwwLDU3LjgyLDYxLjU5di01LjNINDMuNzFaIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNNjMuMTIsMzUuMTJINzlWMjFINjMuMTJBMTkuNDMsMTkuNDMsMCwwLDAsNDMuNzEsNDAuNDF2MS43N0g1Ny44MlY0MC40MUE1LjMsNS4zLDAsMCwxLDYzLjEyLDM1LjEyWiIvPjxwb2x5Z29uIGNsYXNzPSJjbHMtNCIgcG9pbnRzPSI0My43MSA1Ni4yOSA1Ny44MiA1Ni4yOSA1Ny44MiA1Ni4yOSA1Ny44MiA0Mi4xOCA1Ny44MiA0Mi4xOCA0My43MSA0Mi4xOCA0My43MSA1Ni4yOSIvPjwvZz48L2c+PC9zdmc+

),
mediaType: "image/svg+xml"
)
let medias = MetadataViews.Medias([media])
return FungibleTokenMetadataViews.FTDisplay(
name: "FLOW Network Token",
symbol: "FLOW",
description: "FLOW is the protocol token that is required for transaction fees, storage fees, staking, and many applications built on the Flow Blockchain",
externalURL: MetadataViews.ExternalURL("https://flow.com"),
logos: medias,
socials: {
"twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
}
)
case Type<FungibleTokenMetadataViews.FTVaultData>():
return FungibleTokenMetadataViews.FTVaultData(
storagePath: /storage/flowTokenVault,
receiverPath: /public/flowTokenReceiver,
metadataPath: /public/flowTokenBalance,
providerPath: /private/flowTokenVault,
receiverLinkedType: Type<&FlowToken.Vault{FungibleToken.Receiver}>(),
metadataLinkedType: Type<&FlowToken.Vault{FungibleToken.Balance}>(),
providerLinkedType: Type<&FlowToken.Vault{FungibleToken.Provider}>(),
createEmptyVaultFunction: (fun (): @FungibleToken.Vault {
return <-FlowToken.createEmptyVault()
})
)
}
return nil
}
}

// createEmptyVault
Expand Down Expand Up @@ -167,32 +226,32 @@ pub contract FlowToken: FungibleToken {
}
}

init(adminAccount: AuthAccount) {
init() {
joshuahannan marked this conversation as resolved.
Show resolved Hide resolved
self.totalSupply = 0.0

// Create the Vault with the total supply of tokens and save it in storage
//
let vault <- create Vault(balance: self.totalSupply)
adminAccount.save(<-vault, to: /storage/flowTokenVault)
self.account.save(<-vault, to: /storage/flowTokenVault)

// Create a public capability to the stored Vault that only exposes
// the `deposit` method through the `Receiver` interface
//
adminAccount.link<&FlowToken.Vault{FungibleToken.Receiver}>(
self.account.link<&FlowToken.Vault{FungibleToken.Receiver}>(
/public/flowTokenReceiver,
joshuahannan marked this conversation as resolved.
Show resolved Hide resolved
target: /storage/flowTokenVault
)

// Create a public capability to the stored Vault that only exposes
// the `balance` field through the `Balance` interface
//
adminAccount.link<&FlowToken.Vault{FungibleToken.Balance}>(
self.account.link<&FlowToken.Vault{FungibleToken.Balance}>(
/public/flowTokenBalance,
target: /storage/flowTokenVault
)

let admin <- create Administrator()
adminAccount.save(<-admin, to: /storage/flowTokenAdmin)
self.account.save(<-admin, to: /storage/flowTokenAdmin)

// Emit an event that shows that the contract was initialized
emit TokensInitialized(initialSupply: self.totalSupply)
Expand Down
21 changes: 21 additions & 0 deletions lib/go/contracts/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const (
// Each contract has placeholder addresses that need to be replaced
// depending on which network they are being used with
placeholderFungibleTokenAddress = "0xFUNGIBLETOKENADDRESS"
placeholderFungibleTokenMVAddress = "\"./FungibleTokenMetadataViews.cdc\""
placeholderFlowTokenAddress = "0xFLOWTOKENADDRESS"
placeholderIDTableAddress = "0xFLOWIDTABLESTAKINGADDRESS"
placeholderStakingProxyAddress = "0xSTAKINGPROXYADDRESS"
Expand Down Expand Up @@ -89,6 +90,26 @@ func FlowToken(fungibleTokenAddress string) []byte {
withHexPrefix(fungibleTokenAddress),
)

code = strings.ReplaceAll(
code,
placeholderFungibleTokenMVAddress,
withHexPrefix(fungibleTokenAddress),
)

// Replace the init method storage operations
code = strings.ReplaceAll(
code,
"self.account.",
"adminAccount.",
)

// Replace the init method admin account parameter
code = strings.ReplaceAll(
code,
"init()",
"init(adminAccount: AuthAccount)",
)

return []byte(code)
}

Expand Down
Loading