---
sidebar_position: 4
---

# Token Offerings

A bonding curve accepts tokens in exchange for minting new tokens.

What then, if you either (a) do not want to give up mint authority or (b) want 
to sell some tokens that have already been minted? This is where token offerings come into play

In a token offering, a bonding curve and a fungible entangler are created.

  * A bonding curve that accepts the base mint (i.e. sol) and mints an intermediary token
  * A fungible entangler that can swap between the intermediary token and the output token.

This system allows two way swaps, so buyers can sell their tokens back for base tokens, although the 
price will potentially have fluctuated between their purchase and their sell. This behaviour can be disabled to 
make it only one way.

## Create a Token Offering

Creating a token offering comes in two steps. First, we create a sale using a bonding curve. 
Then, we create the fungible entangler. For your token offering, you can decide between having a fixed sale price
or using a dynamic pricing mechanism. You can also customise the curve used by your dynamic pricing. See the 
LBC page for more information.

First, create a token which we plan to offer:

```jsx async name=sell_token
var { mint: sellMint } = await marketplaceSdk.createManualToken({
  metadata: new DataV2({
    // Max name len 32
    name: "Token we are Selling",
    symbol: "weSELL",
    uri: "",
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null,
  }),
  decimals: 0,
  amount: 1000,
})
```

Here's a fixed price sale of 100 of these tokens for 0.01 SOL.

```jsx async name=fixed-sale deps=sell_token
var marketItemInstrs = await marketplaceSdk.createMarketItemInstructions({
  metadata: new DataV2({
    // Max name len 32
    name: "Intermediary Token",
    symbol: "inter",
    uri: "",
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null,
  }),
  quantity: 100,
  price: 0.01,
  baseMint: NATIVE_MINT,
  bondingArgs: {
    targetMintDecimals: 0,
  },
});

var entanglerInstrs = await fungibleEntanglerSdk.createFungibleEntanglerInstructions({
  amount: 100, // deposit 100 sellMint tokens to be sold
  parentMint: sellMint,
  childMint: marketItemInstrs.output.targetMint, // mint of the intermediary token
});

await sendMultipleInstructions(
  marketplaceSdk.tokenBondingSdk.errors || new Map(),
  marketplaceSdk.provider,
  [...marketItemInstrs.instructions, entanglerInstrs.instructions],
  [...marketItemInstrs.signers, entanglerInstrs.signers]
);
```

Here's a dynamic pricing sale. Here it will start at 0.05 SOL and fall to 0.01 SOL over 5 minutes.
In a Strata token offering, the offering is reversible, i.e. users can sell their tokens for the current price back for SOL.
If you don't want users to be able to sell, set sellFrozen to true.

```jsx async name=lbc-sale deps=sell_token
var lbcInstructions = await marketplaceSdk.createLiquidityBootstrapperInstructions({
  baseMint: NATIVE_MINT,
  startPrice: 0.05,
  minPrice: 0.01,
  interval: 5 * 60 * 60,
  maxSupply: 100,
  bondingArgs: {
    targetMintDecimals: 0,
    sellFrozen: false,
  },
});

var entanglerInstrs = await fungibleEntanglerSdk.createFungibleEntanglerInstructions({
  amount: 100, // deposit 100 sellMint tokens to be sold
  parentMint: sellMint,
  childMint: marketItemInstrs.output.targetMint, // mint of the intermediary token
});

await sendMultipleInstructions(
  marketplaceSdk.tokenBondingSdk.errors || new Map(),
  marketplaceSdk.provider,
  [...marketItemInstrs.instructions, entanglerInstrs.instructions],
  [...marketItemInstrs.signers, entanglerInstrs.signers]
);
```

## Many to One Swap

While only one bonding curve can own a given mint authority, there can be many bonding
curves that allow burning of an intermediary token to get to a target token.

This means that you can create systems that accept multiple tokens to purchase a single token. Note that these
systems are buy only -- you cannot go in the reverse direction.

Let's create three tokens:

  * Offering Token: This is the token we are offering
  * Token A
  * Token B

We will allow purchase of Offering Token with both Token A and Token B.
Note that, while this is a lot of code, you can also do this on the launchpad at app.strataprotocol.com 
by creating two separate fixed price token sales using Sell a Token.

```jsx async name=three_tokens
var offering = await marketplaceSdk.createManualToken({
  metadata: new DataV2({
    // Max name len 32
    name: "Offering Token",
    symbol: "OFF",
    uri: "",
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null,
  }),
  decimals: 0,
  amount: 1000,
});
var a = await marketplaceSdk.createManualToken({
  metadata: new DataV2({
    name: "Token A",
    symbol: "A",
    uri: "",
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null,
  }),
  decimals: 0,
  amount: 1000,
});
var b = await marketplaceSdk.createManualToken({
  metadata: new DataV2({
    name: "Token B",
    symbol: "B",
    uri: "",
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null,
  }),
  decimals: 0,
  amount: 1000,
});
```

Now, let's create a system where we can buy offering using both a and b:

```jsx async name=three_tokens_sale deps=three_tokens
var intermediaryMetadata = new DataV2({
  // Max name len 32
  name: "Intermediary Token",
  symbol: "INTER",
  uri: "",
  sellerFeeBasisPoints: 0,
  creators: null,
  collection: null,
  uses: null,
});
var marketItemInstrs1 = await marketplaceSdk.createMarketItemInstructions({
  metadata: intermediaryMetadata,
  quantity: 10,
  price: 1,
  baseMint: a.mint,
  bondingArgs: {
    targetMintDecimals: 0,
  },
});
var retrievalInstrs1 =
    await fungibleEntanglerSdk.createFungibleEntanglerInstructions({
      amount: 10, // deposit 10 sellMint tokens to be sold
      parentMint: offerring.mint,
      childMint: marketItemInstrs1.output.targetMint, // mint of the intermediary token
    });
var marketItemInstrs2 = await marketplaceSdk.createMarketItemInstructions({
  metadata: intermediaryMetadata,
  quantity: 10,
  price: 2,
  baseMint: b.mint,
  bondingArgs: {
    targetMintDecimals: 0,
  },
});
var retrievalInstrs2 =
    await fungibleEntanglerSdk.createFungibleChildEntanglerInstructions({
      parentEntangler: retrievalInstrs1.output.parentEntangler,
      amount: 10, // deposit 10 sellMint tokens to be sold
      childMint: marketItemInstrs2.output.targetMint, // mint of the intermediary token
    })
await sendMultipleInstructions(
  marketplaceSdk.tokenBondingSdk.errors || new Map(),
  provider,
  [...marketItemInstrs1.instructions, retrievalInstrs1.instructions, ...marketItemInstrs2.instructions, retrievalInstrs2.instructions],
  [...marketItemInstrs1.signers, retrievalInstrs1.signers, ...marketItemInstrs2.signers, retrievalInstrs2.signers]
);
```
