> ## Documentation Index
> Fetch the complete documentation index at: https://neardocs-update-rpc-openapi.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Types and Interface

> Learn how to define your contract's interface and use Rust and SDK types in its inputs, outputs, and state.

export const File = ({children}) => {
  return children;
};

export const Block = ({children}) => {
  return children;
};

export const ExplainCode = ({children}) => {
  const [activeBlock, setActiveBlock] = useState(0);
  const [code, setCode] = useState(null);
  const blockRefs = useRef({});
  const codeContainerRef = useRef(null);
  const ratioMap = useRef({});
  function toRaw(ref) {
    const fullUrl = ref.slice(ref.indexOf('https'));
    const [url] = fullUrl.split('#');
    const [org, repo, , branch, ...pathSeg] = new URL(url).pathname.split('/').slice(1);
    return `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${pathSeg.join('/')}`;
  }
  async function fetchRaw(url, fromLine, toLine) {
    let res;
    if (typeof window !== 'undefined') {
      const validUntil = localStorage.getItem(`${url}-until`);
      if (validUntil && Number(validUntil) > Date.now()) {
        res = localStorage.getItem(url);
      }
    }
    if (!res) {
      try {
        res = await (await fetch(url)).text();
        if (typeof window !== 'undefined') {
          localStorage.setItem(url, res);
          localStorage.setItem(`${url}-until`, String(Date.now() + 60000));
        }
      } catch {
        return 'Error fetching code, please try reloading';
      }
    }
    let lines = res.split('\n');
    const from = fromLine ? Number(fromLine) - 1 : 0;
    const to = toLine ? Number(toLine) : lines.length;
    lines = lines.slice(from, to);
    const indent = lines.reduce((prev, line) => {
      if (!line.length) return prev;
      const m = line.match(/^\s+/);
      return m ? Math.min(prev, m[0].length) : 0;
    }, Infinity);
    return lines.map(l => l.slice(indent === Infinity ? 0 : indent)).join('\n');
  }
  function parseHighlights(str) {
    const set = new Set();
    if (!str) return set;
    String(str).split(',').forEach(part => {
      const [a, b] = part.trim().split('-');
      if (b) {
        for (let i = Number(a); i <= Number(b); i++) set.add(i);
      } else if (a) set.add(Number(a));
    });
    return set;
  }
  const blocks = [];
  const files = [];
  function collect(node) {
    if (!node) return;
    if (Array.isArray(node)) {
      node.forEach(collect);
      return;
    }
    if (typeof node !== 'object' || !node.props) return;
    if (node.props.url !== undefined) {
      files.push({
        ...node.props
      });
    } else if (node.type === Block || node.props.fname !== undefined) {
      blocks.push({
        text: node.props.children,
        highlight: node.props.highlights,
        fname: node.props.fname,
        type: node.props.type
      });
    } else {
      collect(node.props.children);
    }
  }
  collect(children);
  const activeFname = blocks[activeBlock]?.fname || files[0]?.fname;
  const fileKey = activeFname;
  const currentFile = files.find(f => f.fname === activeFname) || files[0];
  useEffect(() => {
    const observedEls = Object.entries(blockRefs.current).filter(([, el]) => el);
    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        const idx = Number(entry.target.dataset.blockIdx);
        ratioMap.current[idx] = entry.intersectionRatio;
      });
      let bestIdx = -1;
      let bestRatio = 0;
      Object.entries(ratioMap.current).forEach(([idx, ratio]) => {
        if (ratio > bestRatio) {
          bestRatio = ratio;
          bestIdx = Number(idx);
        }
      });
      if (bestIdx !== -1) {
        setActiveBlock(bestIdx);
      } else {
        const zoneTop = window.innerHeight * 0.2;
        const allAboveZone = Object.entries(blockRefs.current).filter(([, el]) => el).every(([, el]) => el.getBoundingClientRect().bottom < zoneTop);
        if (allAboveZone) setActiveBlock(-1);
      }
    }, {
      threshold: [0, 0.1, 0.25, 0.5, 0.75, 1],
      rootMargin: '-20% 0px -50% 0px'
    });
    observedEls.forEach(([idx, el]) => {
      el.dataset.blockIdx = idx;
      observer.observe(el);
    });
    return () => observer.disconnect();
  }, [blocks.length]);
  useEffect(() => {
    if (!currentFile?.url) return;
    setCode(null);
    const rawUrl = toRaw(currentFile.url);
    fetchRaw(rawUrl, currentFile.start, currentFile.end).then(setCode);
  }, [fileKey]);
  const highlighted = parseHighlights(blocks[activeBlock]?.highlight);
  const firstHighlightedLine = highlighted.size > 0 ? Math.min(...highlighted) : null;
  useEffect(() => {
    const container = codeContainerRef.current;
    if (!container || code === null || firstHighlightedLine === null) return;
    const frame = requestAnimationFrame(() => {
      const highlightedLine = container.querySelector(`[data-line="${firstHighlightedLine}"], [data-line-number="${firstHighlightedLine}"], pre code > span:nth-child(${firstHighlightedLine})`);
      if (highlightedLine) {
        const offset = highlightedLine.getBoundingClientRect().top - container.getBoundingClientRect().top;
        container.scrollTo({
          top: Math.max(0, container.scrollTop + offset - container.clientHeight / 2 + highlightedLine.clientHeight / 2),
          behavior: 'smooth'
        });
        return;
      }
      const codeElement = container.querySelector('pre code');
      const lineHeight = codeElement ? Number.parseFloat(getComputedStyle(codeElement).lineHeight) : 0;
      container.scrollTo({
        top: Math.max(0, (firstHighlightedLine - 2) * (lineHeight || 24)),
        behavior: 'smooth'
      });
    });
    return () => cancelAnimationFrame(frame);
  }, [activeBlock, code, firstHighlightedLine]);
  return <div className="my-6 not-prose">
      {}
      <div className="flex gap-8 items-start">
        {}
        <div className="flex-[5] flex flex-col gap-3 min-w-0 pb-[40vh]">
          {blocks.map((block, i) => block.type ? <div key={i} ref={el => {
    blockRefs.current[i] = el;
  }}>
              {block.text}
            </div> : <div key={i} ref={el => {
    blockRefs.current[i] = el;
  }} onClick={() => setActiveBlock(i)} className={['cursor-pointer rounded-md px-5 py-4 transition-all duration-200 border-l-4 border-indigo-500', activeBlock === i ? 'shadow-sm' : 'opacity-60 hover:opacity-90'].join(' ')} style={{
    backgroundColor: activeBlock === i ? 'var(--explain-card-active-bg)' : 'var(--explain-card-bg)',
    border: activeBlock === i ? '1px solid var(--explain-card-border)' : '1px solid transparent'
  }}>
              {block.text}
            </div>)}
        </div>

        {}
        {currentFile && <div className="flex-[6] min-w-0 sticky top-6">
            <div ref={codeContainerRef} className="max-h-[calc(100vh-7rem)] overflow-y-auto">
              {code === null ? <div className="p-4 text-xs text-gray-500 dark:text-gray-400">Loading...</div> : <CodeBlock key={`${fileKey}-${activeBlock}`} language="rust" filename={currentFile.fname} lines highlight={JSON.stringify([...highlighted])}>
                  {code}
                </CodeBlock>}
            </div>
            <div className="mt-1 flex justify-end">
              <a href={`${currentFile.url}#L${currentFile.start}-L${currentFile.end}`} target="_blank" rel="noreferrer noopener" className="text-[0.6875rem] font-medium text-[#656d76] no-underline hover:text-[#1f2328] dark:text-[#8b949e] dark:hover:text-[#e6edf3]">
                See on GitHub
              </a>
            </div>
          </div>}
      </div>
    </div>;
};

Smart contracts expose functions so users can interact with them. There are different types of functions including `read-only`, `private` and `payable`.

<ExplainCode>
  <Block highlights="24-34,37-62,64-75,77-79,81-83" fname="auction">
    ### Contract's Interface

    All **public** functions in the contract are part of its **interface**. They can be called by anyone, and are the only way to interact with the contract.
  </Block>

  <Block highlights="" fname="auction" type="details">
    <Accordion title="Exposing trait implementations">
      Functions can also be exposed through trait implementations. This can be useful if implementing a shared interface or standard for a contract. This code generation is handled very similarly to basic `pub` functions, but the `#[near]` macro only needs to be attached to the trait implementation, not the trait itself:

      ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
      pub trait MyTrait {
          fn trait_method(&mut self);
      }

      #[near]
      impl MyTrait for MyContractStructure {
          fn trait_method(&mut self) {
              // .. method logic here
          }
      }
      ```
    </Accordion>
  </Block>

  <Block highlights="22-34" fname="auction">
    ### Initialization Functions

    A contract can opt to have an initialization function. If present, this function must be called before any other to [initialize the contract](./storage).
  </Block>

  <Block highlights="22" fname="auction">
    #### `#[init]`

    The initialization function is marked with the `#[init]` macro.
  </Block>

  <Block highlights="37-62,64-75" fname="auction">
    ### State Changing Functions

    The functions that modify the [state](./storage) or perform [actions](./actions) need to be called by a user with a NEAR account, since a transaction is required to execute them.
  </Block>

  <Block highlights="37,64" fname="auction">
    #### `&mut self`

    State changing functions are those that take a **mutable** reference to `self` in Rust.
  </Block>

  <Block highlights="40,45,46" fname="auction" type="info">
    <Tip>
      The SDK provides [contextual information](./environment), such as which account is calling the function, or what time it is.
    </Tip>
  </Block>

  <Block highlights="77-79,81-83" fname="auction">
    ### Read-Only Functions

    Contract's functions can be read-only, meaning they don't modify the state. Calling them is free for everyone, and does not require to have a NEAR account.
  </Block>

  <Block highlights="77,81" fname="auction">
    #### `&self`

    Read-only functions are those that take an **immutable** reference to `self` in Rust.
  </Block>

  <Block highlights="23" fname="auction">
    ### Private Functions

    Many times you will want to have functions that **are exposed** as part of the contract's interface, but **should not be called directly** by users.

    Besides initialization functions, [callbacks from cross-contract calls](./crosscontract) should always be `private`.

    These functions are marked as `private` in the contract's code, and can only be called by the contract itself.
  </Block>

  <Block highlights="23" fname="auction">
    #### \[#private]

    Private functions are marked using the `#[private]` macro in Rust.
  </Block>

  <Block highlights="36,45" fname="auction">
    ### Payable Functions

    By default, functions will panic if the user attaches NEAR Tokens to the call. Functions that accept NEAR Tokens must be marked as `payable`.

    Within the function, the user will have access to the [attached deposit](./environment).
  </Block>

  <Block highlights="36,45" fname="auction">
    #### \[#payable]

    Payable functions are marked using the `#[payable]` macro in Rust.
  </Block>

  <Block fname="auction">
    ### Internal Functions

    All the functions we covered so far are part of the interface, meaning they can be called by an external actor.

    However, contracts can also have private internal functions - such as helper or utility functions - that are **not exposed** to the outside world.

    To create internal private methods in a Rust contract, do not declare them as public (`pub fn`).
  </Block>

  <Block fname="auction" type="details">
    <Accordion title="Separate impl block">
      Another way of not exporting methods is by having a separate `impl Contract` section, that is not marked with `#[near]`.

      ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
      #[near]
      impl Contract {
          pub fn increment(&mut self) {
              self.internal_increment();
          }
      }
      impl Contract {
          /// This methods is still not exported.
          pub fn internal_increment(&mut self) {
              self.counter += 1;
          }
      }
      ```
    </Accordion>
  </Block>

  <File fname="auction" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/01-basic-auction/src/lib.rs" start="2" end="84" />
</ExplainCode>

***

## SDK types

Smart contracts can receive, store, and return data using native Rust types such as strings, integers, booleans, maps, and vectors. The SDK also provides types for values that need special handling at the contract boundary.

### Large integers

Contracts can store `u64` and `u128` values directly, but JSON consumers cannot always represent them without losing precision. Use the SDK's `U64` and `U128` wrapper types for public inputs and outputs that need to be serialized as strings.

<Warning>
  JavaScript numbers cannot represent every integer above `2^53 - 1`. Keep native integer types in internal contract logic, and use the JSON wrapper types at the external interface when necessary.
</Warning>

### Complex objects

Contracts can receive and return complex Rust structures. Objects used as JSON inputs or outputs need JSON serialization, while structures stored in contract state need Borsh serialization.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
#[near(serializers = [json])]
pub struct Bid {
    pub bidder: AccountId,
    pub amount: U128,
}
```

See [serialization](/smart-contracts/anatomy/serialization) for the difference between interface and state serialization.

### Tokens and accounts

Use `NearToken` to represent NEAR amounts. It provides constructors and accessors for yoctoNEAR, millinear, and NEAR values.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let deposit = NearToken::from_near(1);
let amount = deposit.as_yoctonear();
```

The SDK's `AccountId` type validates NEAR account IDs when values enter the contract. Prefer it to a plain `String` whenever a value represents an account.
