Token Factory - HackMD (2024)

Table of Contents
Read more Sign in FAQs

# Token Factory## Introduction to Building a Token Factory Module with Ignite CLIIn this tutorial, we will guide you through the process of building a token factory module using the Ignite CLI. This module is a powerful tool for creating native denominations (denoms) on your blockchain, providing you with the capability to issue and manage digital assets natively within your network.Digital assets, characterized by their uniqueness and scarcity, are fundamental to the value proposition of blockchain technology. A well-known example is the ERC20 standard on Ethereum, which has gained widespread popularity. By learning to create and manage native denoms on your blockchain, you will gain hands-on experience with one of blockchain's key functionalities.**You will learn how to:*** Develop a module from scratch.* Implement a CRUD (Create, Read, Update, Delete) operation while specifically removing the delete functionality to safeguard the integrity of initialized denoms.* Integrate logic for creating new denoms.* Engage with various components such as the client, types, keeper, expected keeper, and handlers to effectively implement the Token Factory module.**Note:** The code provided in this tutorial is tailored for educational purposes. It is not designed for deployment in production environments.## Understanding the Module DesignThe Token Factory module empowers you to create and manage native denoms on your blockchain. In the Cosmos ecosystem and with Ignite CLI, a denom represents the name of a token that is universally usable. To learn more, see [Denom](denoms.md).## What is a Denom?Denoms are essentially identifiers for tokens on a blockchain, synonymous with terms like 'coin' or 'token'. For an in-depth understanding, refer to the Cosmos SDK's [ADR 024: Coin Metadata](https://docs.cosmos.network/main/build/architecture/adr-024-coin-metadata#context).A denom in this module always has an owner. An owner is allowed to issue new tokens, change the denoms name, and transfer the ownership to a different account. Learn more about [denoms](02-denoms.md).In our Token Factory module:1. Ownership and Control: Each denom is assigned an owner, who has the authority to issue new tokens, rename the denom, and transfer ownership.2. Properties of a Denom: * denom: The unique name of the denom. * description: A brief about the denom. * ticker: The symbolic representation. * precision: Determines the number of decimal places for the denom. * url: Provides additional information. * maxSupply & supply: Define the total and current circulating supply. * canChangeMaxSupply: A boolean indicating if maxSupply can be altered post-issuance. * owner: The account holding ownership rights.3. Proto Definition:```protomessage Denom { string denom = 1; string description = 2; string ticker = 3; int32 precision = 4; string url = 5; int32 maxSupply = 6; int32 supply = 7; bool canChangeMaxSupply = 8; string owner = 9;}```### Core Functionalities* Issuing new tokens.* Transferring ownership of tokens.* Keeping a ledger of all tokens.## Chapter 2: Getting Started with Your Token Factory ModuleWelcome to the next step in your journey of building a token factory module. In this chapter, we'll walk you through setting up your blockchain and beginning the development of your token factory module.### Setting up your blockchainFirst, we'll scaffold a new blockchain specifically for your token factory. We use the --no-module flag to ensure that we add the token factory module with the required dependencies later. Run the following command in your terminal:```bashignite scaffold chain tokenfactory --no-module```This command establishes a new Cosmos SDK blockchain named `tokenfactory` and places it in a directory of the same name. Inside this directory, you'll find a fully functional blockchain ready for further customization.Now, navigate into your newly created blockchain directory:```bashcd tokenfactory```### Scaffold Your Token Factory ModuleNext, we'll scaffold a new module for your token factory. This module will depend on the Cosmos SDK's [bank](https://docs.cosmos.network/main/build/modules/bank#abstract) and [auth](https://docs.cosmos.network/main/build/modules/auth#abstract) modules, which provide essential functionalities like account access and token management. Use the following command:```bashignite scaffold module tokenfactory --dep account,bank```The successful execution of this command will be confirmed with a message indicating that the `tokenfactory` module has been created.### Defining Denom Data StructureTo manage denoms within your token factory, define their structure using an Ignite map. This will store the data as key-value pairs. Run this command:```bashignite scaffold map Denom description:string ticker:string precision:int url:string maxSupply:int supply:int canChangeMaxSupply:bool --signer owner --index denom --module tokenfactory```Review the `proto/tokenfactory/tokenfactory/denom.proto` file to see the scaffolding results, which include modifications to various files indicating successful creation of the denom structure.### Git CommitAfter scaffolding your denom map, it's a good practice to save your progress. Use the following commands to make your first Git commit:```bashgit add .git commit -m "Add tokenfactory module and denom map"```This saves a snapshot of your project, allowing you to revert back if needed.## Removing Delete FunctionalityIn a blockchain context, once a denom is created, it's crucial to ensure it remains immutable and cannot be deleted. This immutability is key to maintaining the integrity and trust in the blockchain. Therefore, we'll remove the delete functionality from the scaffolded CRUD operations. Follow these steps:### Proto AdjustmentsIn `proto/tokenfactory/tokenfactory/tx.proto`, remove the `DeleteDenom` RPC method and the associated message types.### Client UpdatesNavigate to the client in `x/tokenfactory/module/autocli.go` and make these changes:* Remove the entire `DeleteDenom` RpcMethod### Keeper Modifications* In `x/tokenfactory/keeper/denom_test.go`, remove `TestDenomRemove()`.* From `denom.go` remove the `RemoveDenom()` function.* From `msg_server_denom_test.go` and `msg_server_denom.go` remove the `TestDenomMsgServerDelete()` and `DeleteDenom()` functions , respectively.### Types Directory Changes* Update `x/tokenfactory/types/codec.go` to remove references to `MsgDeleteDenom`.* Remove `TestMsgDeleteDenom_ValidateBasic()` from `x/tokenfactory/types/messages_denom_test.go`.* Eliminate all references to `MsgDeleteDenom()` in `x/tokenfactory/types/messages_denom.go`.After making these changes, commit your updates:```bashgit add .git commit -m "Remove the delete denom functionality"```This concludes the second chapter, setting a solid foundation for your token factory module. In the next chapter, we'll delve into implementing the application logic that will bring your token factory to life.## Chapter 3: Implementing Core Functionality in Your Token FactoryHaving disabled the deletion of denoms, we now turn our attention to the heart of the token factory module: defining the structure of new denoms and implementing their creation and update logic.### Proto Definition UpdatesStart by defining the structure of a new token denom in `proto/tokenfactory/tokenfactory/tx.proto`.For `MsgCreateDenom`:* Remove `int32 supply = 8;` and adjust the field order so `canChangeMaxSupply` becomes the 8th field.Resulting `MsgCreateDenom` message:```protomessage MsgCreateDenom { option (cosmos.msg.v1.signer) = "owner"; string owner = 1; string denom = 2; string description = 3; string ticker = 4; int32 precision = 5; string url = 6; int32 maxSupply = 7; bool canChangeMaxSupply = 8;}```For `MsgUpdateDenom`:* Omit `string ticker = 4;`, `int32 precision = 5;`, and `int32 supply = 8;`, and reorder the remaining fields.Resulting `MsgUpdateDenom` message:```protomessage MsgUpdateDenom { option (cosmos.msg.v1.signer) = "owner"; string owner = 1; string denom = 2; string description = 3; string url = 4; int32 maxSupply = 5; bool canChangeMaxSupply = 6;}```### Types UpdatesWhen creating new denoms, they initially have no supply. The supply is determined only when tokens are minted.In `x/tokenfactory/types/messages_denom.go`:* Remove the `supply` parameter from `NewMsgCreateDenom`.* Update `NewMsgUpdateDenom` to exclude unchangeable parameters like `ticker`, `precision`, and `supply`.The same changes need to be applied to `x/tokenfactory/module/aucli.go`.Remove the `supply` from `CreateDenom` and the `ticker`, `precision`, and `supply` from `UpdateDemon` commands:```goTx: &autocliv1.ServiceCommandDescriptor{ Service: modulev1.Msg_ServiceDesc.ServiceName, EnhanceCustomCommand: true, // only required if you want to use the custom command RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "UpdateParams", Skip: true, // skipped because authority gated }, { RpcMethod: "CreateDenom", Use: "create-denom [denom] [description] [ticker] [precision] [url] [maxSupply] [canChangeMaxSupply]", Short: "Create a new Denom", PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}, {ProtoField: "description"}, {ProtoField: "ticker"}, {ProtoField: "precision"}, {ProtoField: "url"}, {ProtoField: "maxSupply"}, {ProtoField: "canChangeMaxSupply"}}, }, { RpcMethod: "UpdateDenom", Use: "update-denom [denom] [description] [url] [maxSupply] [canChangeMaxSupply]", Short: "Update Denom", PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}, {ProtoField: "description"}, {ProtoField: "url"}, {ProtoField: "maxSupply"}, {ProtoField: "canChangeMaxSupply"}}, }, // this line is used by ignite scaffolding # autocli/tx },```### Keeper LogicThe keeper is where you define the business logic for manipulating the database and writing to the key-value store.**In `x/tokenfactory/keeper/msg_server_denom.go`:*** Update `CreateDenom()` to include logic for creating unique denoms. Modify the error message to point to existing denoms. Set `Supply` to `0`.* Modify `UpdateDenom()` to verify ownership and manage max supply changes.```gofunc (k msgServer) UpdateDenom(goCtx context.Context, msg *types.MsgUpdateDenom) (*types.MsgUpdateDenomResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // Check if the value exists valFound, isFound := k.GetDenom( ctx, msg.Denom, ) if !isFound { return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "Denom to update not found") } // Checks if the the msg owner is the same as the current owner if msg.Owner != valFound.Owner { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner") } if !valFound.CanChangeMaxSupply && valFound.MaxSupply != msg.MaxSupply { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "cannot change maxsupply") } if !valFound.CanChangeMaxSupply && msg.CanChangeMaxSupply { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Cannot revert change maxsupply flag") } var denom = types.Denom{ Owner: msg.Owner, Denom: msg.Denom, Description: msg.Description, Url: msg.Url, MaxSupply: msg.MaxSupply, CanChangeMaxSupply: msg.CanChangeMaxSupply, } k.SetDenom(ctx, denom) return &types.MsgUpdateDenomResponse{}, nil}```### Expected Keepers`x/tokenfactory/types/expected_keepers.go` is where you define interactions with other modules. Since your module relies on the `auth` and `bank` modules, specify which of their functions your module can access.Replace the existing code in `expected_keepers.go` with the updated definitions that interface with `auth` and `bank` modules.```gopackage typesimport ( "context" sdk "github.com/cosmos/cosmos-sdk/types")type AccountKeeper interface { GetModuleAddress(moduleName string) sdk.AccAddress GetModuleAccount(ctx context.Context, moduleName string) sdk.ModuleAccountI GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI}type BankKeeper interface { SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins}// ParamSubspace defines the expected Subspace interface for parameters.type ParamSubspace interface { Get(context.Context, []byte, interface{}) Set(context.Context, []byte, interface{})}```### Commiting Your ChangesRegular commits are vital for tracking progress and ensuring a stable rollback point if needed. After implementing these changes, use the following commands to commit:```bashgit add .git commit -m "Add token factory create and update logic"```To review your progress, use `git log` to see the list of commits, illustrating the journey from initialization to the current state of your module.## Chapter 4: Expanding Functionality with New MessagesIn this chapter, we focus on enhancing the token factory module by adding two critical messages: `MintAndSendTokens` and `UpdateOwner`. These functionalities are key to managing tokens within your blockchain.### Scaffolding New Messages**MintAndSendTokens:**This message allows the creation (minting) of new tokens and their allocation to a specified recipient. The necessary inputs are the denom, the amount to mint, and the recipient's address.Scaffold this message with:```bashignite scaffold message MintAndSendTokens denom:string amount:int recipient:string --module tokenfactory --signer owner```**UpdateOwner:**This message facilitates the transfer of ownership of a denom. It requires the denom name and the new owner's address.Scaffold this message with:```bashignite scaffold message UpdateOwner denom:string newOwner:string --module tokenfactory --signer owner```### Implementing Logic for New Messages**In the `MintAndSendTokens` Functionality:**Located in `x/tokenfactory/keeper/msg_server_mint_and_send_tokens.go`, this function encompasses the logic for minting new tokens. Key steps include:* Verifying the existence and ownership of the denom.* Ensuring minting does not exceed the maximum supply.* Minting the specified amount and sending it to the recipient.**In the `UpdateOwner` Functionality:**Found in `x/tokenfactory/keeper/msg_server_update_owner.go`, this function allows transferring ownership of a denom. It involves:* Checking if the denom exists.* Ensuring that the request comes from the current owner.* Updating the owner field in the denom's record.### Mint & Update Keeper Logic* For `MintAndSendTokens`, add logic to mint new tokens as per the request parameters. This includes checking for maximum supply limits and transferring the minted tokens to the specified recipient.Navigate to `x/tokenfactory/keeper/msg_server_mint_and_send_tokens.go`.```gopackage keeperimport ( "context" sdk "github.com/cosmos/cosmos-sdk/types" errorsmod "cosmossdk.io/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "tokenfactory/x/tokenfactory/types")func (k msgServer) MintAndSendTokens(goCtx context.Context, msg *types.MsgMintAndSendTokens) (*types.MsgMintAndSendTokensResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // Check if the value exists valFound, isFound := k.GetDenom( ctx, msg.Denom, ) if !isFound { return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "denom does not exist") } // Checks if the the msg owner is the same as the current owner if msg.Owner != valFound.Owner { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner") } if valFound.Supply+msg.Amount > valFound.MaxSupply { return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Cannot mint more than Max Supply") } moduleAcct := k.accountKeeper.GetModuleAddress(types.ModuleName) recipientAddress, err := sdk.AccAddressFromBech32(msg.Recipient) if err != nil { return nil, err } var mintCoins sdk.Coins mintCoins = mintCoins.Add(sdk.NewCoin(msg.Denom, sdk.NewInt(int64(msg.Amount)))) if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, mintCoins); err != nil { return nil, err } if err := k.bankKeeper.SendCoins(ctx, moduleAcct, recipientAddress, mintCoins); err != nil { return nil, err } var denom = types.Denom{ Owner: valFound.Owner, Denom: valFound.Denom, Description: valFound.Description, MaxSupply: valFound.MaxSupply, Supply: valFound.Supply + msg.Amount, Precision: valFound.Precision, Ticker: valFound.Ticker, Url: valFound.Url, CanChangeMaxSupply: valFound.CanChangeMaxSupply, } k.SetDenom( ctx, denom, ) return &types.MsgMintAndSendTokensResponse{}, nil}```* For `UpdateOwner`, implement the logic to update the owner of a denom, ensuring that only the current owner can initiate this change.Navigate to `x/tokenfactory/keeper/msg_server_update_owner.go`.```gopackage keeperimport ( "context" sdk "github.com/cosmos/cosmos-sdk/types" errorsmod "cosmossdk.io/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "tokenfactory/x/tokenfactory/types")func (k msgServer) UpdateOwner(goCtx context.Context, msg *types.MsgUpdateOwner) (*types.MsgUpdateOwnerResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // Check if the value exists valFound, isFound := k.GetDenom( ctx, msg.Denom, ) if !isFound { return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "denom does not exist") } // Checks if the the msg owner is the same as the current owner if msg.Owner != valFound.Owner { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner") } var denom = types.Denom{ Owner: msg.NewOwner, Denom: msg.Denom, Description: valFound.Description, MaxSupply: valFound.MaxSupply, Supply: valFound.Supply, Precision: valFound.Precision, Ticker: valFound.Ticker, Url: valFound.Url, CanChangeMaxSupply: valFound.CanChangeMaxSupply, } k.SetDenom( ctx, denom, ) return &types.MsgUpdateOwnerResponse{}, nil}```### Committing Your ChangesAfter implementing these new functionalities, it's crucial to save your progress. Use the following commands:```bashgit add .git commit -m "Add minting and sending functionality"```This commit not only tracks your latest changes but also acts as a checkpoint to which you can revert if needed.## Chapter 5: Walkthrough and Manual Testing of the Token Factory ModuleCongratulations on reaching the final stage! It's time to put your token factory module to the test. This walkthrough will guide you through building, starting your chain, and testing the functionalities you've implemented.### Building and Starting the ChainFirst, build and initiate your blockchain:```bashignite chain serve```Keep this terminal running as you proceed with the tests.### Testing Functionalities**1. Creating a New Denom:*** First, let's set our chain-id into the config:```bashtokenfactoryd config set client chain-id tokenfactory```* In a new terminal, create a denom named uignite with the command:```bashtokenfactoryd tx tokenfactory create-denom uignite "My denom" IGNITE 6 "some/url" 1000000000 true --from alice```* Confirm the transaction in your blockchain.**2. Querying the Denom:**Check the list of denoms to see your new creation:```bashtokenfactoryd query tokenfactory list-denom```**3. Updating the Denom:*** Modify the uignite denom:```bashtokenfactoryd tx tokenfactory update-denom uignite "Ignite" "newurl" 2000000000 false --from alice```* Query the denoms again to observe the changes:```bashtokenfactoryd query tokenfactory list-denom```**4. Minting and Sending Tokens:*** Mint uignite tokens and send them to a recipient:```bashtokenfactoryd tx tokenfactory mint-and-send-tokens uignite 1200 cosmos16x46rxvtkmgph6jnkqs80tzlzk6wpy6ftrgh6t --from alice```* Check the recipient’s balance:```bashtokenfactoryd query bank balances cosmos16x46rxvtkmgph6jnkqs80tzlzk6wpy6ftrgh6t```* Verify the updated supply in denom list:```bashtokenfactoryd query tokenfactory list-denom```**5. Transferring Ownership:*** Transfer the ownership of uignite:```bashtokenfactoryd tx tokenfactory update-owner uignite cosmos16x46rxvtkmgph6jnkqs80tzlzk6wpy6ftrgh6t --from alice```* Confirm the ownership change:```bashtokenfactoryd query tokenfactory list-denom```**6. Confirming Minting Restrictions:*** Test minting with alice to ensure restrictions apply:```bashtokenfactoryd tx tokenfactory mint-and-send-tokens uignite 1200 cosmos16x46rxvtkmgph6jnkqs80tzlzk6wpy6ftrgh6t --from alice```Check your transaction:```bashtokenfactoryd query tx <txhash>```## CongratulationsYou've successfully built and tested a token factory module. This advanced tutorial has equipped you with the skills to:* Integrate other modules and utilize their functionalities.* Customize CRUD operations to fit your blockchain's needs.* Scaffold modules and messages effectively.## Looking Ahead: IBC FunctionalityAs you progress, the next learning adventure involves exploring IBC (Inter-Blockchain Communication). If you're up for a challenge, consider adding IBC functionality to your token factory module. This will not only enhance your module's capabilities but also deepen your understanding of the Cosmos ecosystem.

Last changed by

Read more

Consensus Mechanisms In the realm of blockchain technology, consensus mechanisms play a pivotal role in ensuring the integrity and security of the distributed ledger. These mechanisms govern how nodes on a blockchain reach agreement on the state of the network, preventing double-spending and ensuring the immutability of transactions. 5/21/2024 Loyalty Points and Rewards Module Loyalty programs are popular tools for businesses to enhance customer retention and increase engagement. A blockchain-based loyalty points system offers transparency, security, and ease of use for both the issuer and the customer. 4/11/2024 Chain Simulations with Ignite CLI Chain simulation is a powerful tool in blockchain development, allowing developers to perform fuzz testing and benchmarking through randomized inputs. It simulates messages, blocks, and accounts, providing crucial insights into the performance and stability of your blockchain. 3/27/2024 Supply Chain Tracking System This tutorial outlines the process of creating a blockchain-based supply chain tracking system using Ignite CLI. The system enables businesses to transparently track products from production to delivery. 3/26/2024

Read more from Tendermint DevX

Published on HackMD

Sign in

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox

Sign in with Wallet Wallet ( )

Connect another wallet

New to HackMD? Sign up

Token Factory - HackMD (2024)

FAQs

What is token factory? ›

A token factory is a smart contract that facilitates the creation of various types of tokens within a specific standard, such as ERC-20, ERC-721, or ERC-1155.

How to get rid of token factory frame? ›

Look for dodgy items related to TokenFactoryIframe pop-up virus (see logic highlighted in subsections above) and drag the suspects to the Trash. Find the app that clearly doesn't belong there and move it to the Trash. If this action requires your admin password for confirmation, go ahead and enter it.

How do token payments work? ›

Token payments are a low arrangement offered to a creditor. It can be anything from £1 a month to show that you want to repay the debt. Token payments will not resolve your debt problems, so it is important to work towards a long-term solution.

Top Articles
How to Scan NFC Tags or QR Codes
Man Sues Airbnb Host For Sending His Photos With Another Woman To Wife - News18
Skyward Sinton
Mcgeorge Academic Calendar
Nehemiah 4:1–23
30 Insanely Useful Websites You Probably Don't Know About
Comcast Xfinity Outage in Kipton, Ohio
Hendersonville (Tennessee) – Travel guide at Wikivoyage
Green Bay Press Gazette Obituary
Kent And Pelczar Obituaries
Carter Joseph Hopf
Fire Rescue 1 Login
Which Is A Popular Southern Hemisphere Destination Microsoft Rewards
Www.paystubportal.com/7-11 Login
Https //Advanceautoparts.4Myrebate.com
Thotsbook Com
ocala cars & trucks - by owner - craigslist
Cbs Trade Value Chart Fantasy Football
Viprow Golf
Arre St Wv Srj
Hellraiser III [1996] [R] - 5.8.6 | Parents' Guide & Review | Kids-In-Mind.com
Nhl Tankathon Mock Draft
Decosmo Industrial Auctions
Best Mechanics Near You - Brake Masters Auto Repair Shops
The Ultimate Guide to Extras Casting: Everything You Need to Know - MyCastingFile
Noaa Duluth Mn
Stoney's Pizza & Gaming Parlor Danville Menu
Sodium azide 1% in aqueous solution
Little Rock Skipthegames
At&T Outage Today 2022 Map
Foolproof Module 6 Test Answers
Xpanas Indo
Mami No 1 Ott
Miles City Montana Craigslist
lol Did he score on me ?
Grove City Craigslist Pets
Used 2 Seater Go Karts
60 Second Burger Run Unblocked
How to Draw a Bubble Letter M in 5 Easy Steps
Sun Haven Pufferfish
How to Watch the X Trilogy Starring Mia Goth in Chronological Order
Cvb Location Code Lookup
Directions To 401 East Chestnut Street Louisville Kentucky
Greater Keene Men's Softball
Cherry Spa Madison
Barber Gym Quantico Hours
Mars Petcare 2037 American Italian Way Columbia Sc
One Main Branch Locator
Htb Forums
Panorama Charter Portal
Bellelement.com Review: Real Store or A Scam? Read This
What Time Do Papa John's Pizza Close
Latest Posts
Article information

Author: Amb. Frankie Simonis

Last Updated:

Views: 6162

Rating: 4.6 / 5 (56 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Amb. Frankie Simonis

Birthday: 1998-02-19

Address: 64841 Delmar Isle, North Wiley, OR 74073

Phone: +17844167847676

Job: Forward IT Agent

Hobby: LARPing, Kitesurfing, Sewing, Digital arts, Sand art, Gardening, Dance

Introduction: My name is Amb. Frankie Simonis, I am a hilarious, enchanting, energetic, cooperative, innocent, cute, joyous person who loves writing and wants to share my knowledge and understanding with you.