anchor/tutorials/tutorial-3.html

118 lines
30 KiB
HTML

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Cross Program Invocations (CPI) | ⚓ Anchor</title>
<meta name="generator" content="VuePress 1.8.2">
<link rel="icon" href="data:image/svg+xml,&lt;svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22&gt;&lt;text y=%22.9em%22 font-size=%2290%22&gt;⚓ &lt;/text&gt;&lt;/svg&gt;">
<meta name="description" content="">
<meta name="theme-color" content="#3eaf7c">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="preload" href="/anchor/assets/css/0.styles.21b321ec.css" as="style"><link rel="preload" href="/anchor/assets/js/app.b2f13cd7.js" as="script"><link rel="preload" href="/anchor/assets/js/2.90291299.js" as="script"><link rel="preload" href="/anchor/assets/js/20.50564768.js" as="script"><link rel="prefetch" href="/anchor/assets/js/10.99d917b5.js"><link rel="prefetch" href="/anchor/assets/js/11.45e25cc5.js"><link rel="prefetch" href="/anchor/assets/js/12.d30544e0.js"><link rel="prefetch" href="/anchor/assets/js/13.7bb3490d.js"><link rel="prefetch" href="/anchor/assets/js/14.258e35e3.js"><link rel="prefetch" href="/anchor/assets/js/15.243176ff.js"><link rel="prefetch" href="/anchor/assets/js/16.b6cb9e25.js"><link rel="prefetch" href="/anchor/assets/js/17.29eac49f.js"><link rel="prefetch" href="/anchor/assets/js/18.db5dc2ee.js"><link rel="prefetch" href="/anchor/assets/js/19.b9ce785c.js"><link rel="prefetch" href="/anchor/assets/js/21.b31f2925.js"><link rel="prefetch" href="/anchor/assets/js/3.397fd877.js"><link rel="prefetch" href="/anchor/assets/js/4.f90252b7.js"><link rel="prefetch" href="/anchor/assets/js/5.47891694.js"><link rel="prefetch" href="/anchor/assets/js/6.493f79e9.js"><link rel="prefetch" href="/anchor/assets/js/7.32936426.js"><link rel="prefetch" href="/anchor/assets/js/8.9fc829e7.js"><link rel="prefetch" href="/anchor/assets/js/9.525a5964.js">
<link rel="stylesheet" href="/anchor/assets/css/0.styles.21b321ec.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/anchor/" class="home-link router-link-active"><!----> <span class="site-name">⚓ Anchor</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="https://book.anchor-lang.com" target="_blank" rel="noopener noreferrer" class="nav-link external">
The Anchor Book
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://docs.rs/anchor-lang/latest/anchor_lang/" target="_blank" rel="noopener noreferrer" class="nav-link external">
Rust
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://project-serum.github.io/anchor/ts/index.html" target="_blank" rel="noopener noreferrer" class="nav-link external">
TypeScript
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://github.com/project-serum/anchor" target="_blank" rel="noopener noreferrer" class="nav-link external">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="https://book.anchor-lang.com" target="_blank" rel="noopener noreferrer" class="nav-link external">
The Anchor Book
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://docs.rs/anchor-lang/latest/anchor_lang/" target="_blank" rel="noopener noreferrer" class="nav-link external">
Rust
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://project-serum.github.io/anchor/ts/index.html" target="_blank" rel="noopener noreferrer" class="nav-link external">
TypeScript
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://github.com/project-serum/anchor" target="_blank" rel="noopener noreferrer" class="nav-link external">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Getting Started</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/getting-started/introduction.html" class="sidebar-link">Introduction</a></li><li><a href="/anchor/getting-started/installation.html" class="sidebar-link">Installing Dependencies</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Teams</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/getting-started/projects.html" class="sidebar-link">Projects</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Tutorials</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/tutorials/tutorial-0.html" class="sidebar-link">A Minimal Example</a></li><li><a href="/anchor/tutorials/tutorial-1.html" class="sidebar-link">Arguments and Accounts</a></li><li><a href="/anchor/tutorials/tutorial-2.html" class="sidebar-link">Account Constraints and Access Control</a></li><li><a href="/anchor/tutorials/tutorial-3.html" aria-current="page" class="active sidebar-link">Cross Program Invocations (CPI)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#clone-the-repo" class="sidebar-link">Clone the Repo</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#defining-a-puppet-program" class="sidebar-link">Defining a Puppet Program</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#defining-a-puppet-master-program" class="sidebar-link">Defining a Puppet Master Program</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#signer-seeds" class="sidebar-link">Signer Seeds</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#return-values" class="sidebar-link">Return values</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#conclusion" class="sidebar-link">Conclusion</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-3.html#next-steps" class="sidebar-link">Next Steps</a></li></ul></li><li><a href="/anchor/tutorials/tutorial-4.html" class="sidebar-link">Errors</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>CLI</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/cli/commands.html" class="sidebar-link">Commands</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Source Verification</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/getting-started/verification.html" class="sidebar-link">Verifiable Builds</a></li><li><a href="/anchor/getting-started/publishing.html" class="sidebar-link">Publishing Source</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="cross-program-invocations-cpi"><a href="#cross-program-invocations-cpi" class="header-anchor">#</a> Cross Program Invocations (CPI)</h1> <p>This tutorial covers how to call one program from another, a process known as
<em>cross-program-invocation</em> (CPI).</p> <h2 id="clone-the-repo"><a href="#clone-the-repo" class="header-anchor">#</a> Clone the Repo</h2> <p>To get started, clone the repo.</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">git</span> clone https://github.com/project-serum/anchor
</code></pre></div><p>Change directories to the <a href="https://github.com/project-serum/anchor/tree/master/examples/tutorial/basic-3" target="_blank" rel="noopener noreferrer">example<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>.</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token builtin class-name">cd</span> anchor/examples/tutorial/basic-3
</code></pre></div><p>And install any additional JavaScript dependencies:</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">yarn</span> <span class="token function">install</span>
</code></pre></div><h2 id="defining-a-puppet-program"><a href="#defining-a-puppet-program" class="header-anchor">#</a> Defining a Puppet Program</h2> <p>We start with the program that will be called by another program, the puppet.</p> <div class="language-rs extra-class"><pre class="language-rs"><code><span class="token keyword">use</span> <span class="token namespace">anchor_lang<span class="token punctuation">::</span>prelude<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token macro property">declare_id!</span><span class="token punctuation">(</span><span class="token string">&quot;Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token attribute attr-name">#[program]</span>
<span class="token keyword">pub</span> <span class="token keyword">mod</span> <span class="token module-declaration namespace">puppet</span> <span class="token punctuation">{</span>
<span class="token keyword">use</span> <span class="token keyword">super</span><span class="token punctuation">::</span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">initialize</span><span class="token punctuation">(</span>_ctx<span class="token punctuation">:</span> <span class="token class-name">Context</span><span class="token operator">&lt;</span><span class="token class-name">Initialize</span><span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">set_data</span><span class="token punctuation">(</span>ctx<span class="token punctuation">:</span> <span class="token class-name">Context</span><span class="token operator">&lt;</span><span class="token class-name">SetData</span><span class="token operator">&gt;</span><span class="token punctuation">,</span> data<span class="token punctuation">:</span> <span class="token keyword">u64</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> puppet <span class="token operator">=</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> ctx<span class="token punctuation">.</span>accounts<span class="token punctuation">.</span>puppet<span class="token punctuation">;</span>
puppet<span class="token punctuation">.</span>data <span class="token operator">=</span> data<span class="token punctuation">;</span>
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token attribute attr-name">#[derive(Accounts)]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Initialize</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token attribute attr-name">#[account(init, payer = user, space = 8 + 8)]</span>
<span class="token keyword">pub</span> puppet<span class="token punctuation">:</span> <span class="token class-name">Account</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Data</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token attribute attr-name">#[account(mut)]</span>
<span class="token keyword">pub</span> user<span class="token punctuation">:</span> <span class="token class-name">Signer</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> system_program<span class="token punctuation">:</span> <span class="token class-name">Program</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">System</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token attribute attr-name">#[derive(Accounts)]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">SetData</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token attribute attr-name">#[account(mut)]</span>
<span class="token keyword">pub</span> puppet<span class="token punctuation">:</span> <span class="token class-name">Account</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Data</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token attribute attr-name">#[account]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Data</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> data<span class="token punctuation">:</span> <span class="token keyword">u64</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>If you've followed along the other tutorials, this should be straight forward. We have
a program with two instructions, <code>initialize</code>, which does nothing other than the
initialization of the account (remember, the program <em>transparently</em> prepends a unique 8
byte discriminator the first time an account is used), and <code>set_data</code>, which takes a previously
initialized account, and sets its data field.</p> <p>Now, suppose we wanted to call <code>set_data</code> from another program.</p> <h2 id="defining-a-puppet-master-program"><a href="#defining-a-puppet-master-program" class="header-anchor">#</a> Defining a Puppet Master Program</h2> <p>We define a new <code>puppet-master</code> crate, which successfully executes the Puppet program's <code>set_data</code>
instruction via CPI.</p> <div class="language-rs extra-class"><pre class="language-rs"><code><span class="token keyword">use</span> <span class="token namespace">anchor_lang<span class="token punctuation">::</span>prelude<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">puppet<span class="token punctuation">::</span>cpi<span class="token punctuation">::</span>accounts<span class="token punctuation">::</span></span><span class="token class-name">SetData</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">puppet<span class="token punctuation">::</span>program<span class="token punctuation">::</span></span><span class="token class-name">Puppet</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">puppet<span class="token punctuation">::</span></span><span class="token punctuation">{</span><span class="token keyword">self</span><span class="token punctuation">,</span> <span class="token class-name">Data</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token macro property">declare_id!</span><span class="token punctuation">(</span><span class="token string">&quot;HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token attribute attr-name">#[program]</span>
<span class="token keyword">mod</span> <span class="token module-declaration namespace">puppet_master</span> <span class="token punctuation">{</span>
<span class="token keyword">use</span> <span class="token keyword">super</span><span class="token punctuation">::</span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">pull_strings</span><span class="token punctuation">(</span>ctx<span class="token punctuation">:</span> <span class="token class-name">Context</span><span class="token operator">&lt;</span><span class="token class-name">PullStrings</span><span class="token operator">&gt;</span><span class="token punctuation">,</span> data<span class="token punctuation">:</span> <span class="token keyword">u64</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">anchor_lang<span class="token punctuation">::</span></span><span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> cpi_program <span class="token operator">=</span> ctx<span class="token punctuation">.</span>accounts<span class="token punctuation">.</span>puppet_program<span class="token punctuation">.</span><span class="token function">to_account_info</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> cpi_accounts <span class="token operator">=</span> <span class="token class-name">SetData</span> <span class="token punctuation">{</span>
puppet<span class="token punctuation">:</span> ctx<span class="token punctuation">.</span>accounts<span class="token punctuation">.</span>puppet<span class="token punctuation">.</span><span class="token function">to_account_info</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> cpi_ctx <span class="token operator">=</span> <span class="token class-name">CpiContext</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>cpi_program<span class="token punctuation">,</span> cpi_accounts<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token namespace">puppet<span class="token punctuation">::</span>cpi<span class="token punctuation">::</span></span><span class="token function">set_data</span><span class="token punctuation">(</span>cpi_ctx<span class="token punctuation">,</span> data<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token attribute attr-name">#[derive(Accounts)]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">PullStrings</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token attribute attr-name">#[account(mut)]</span>
<span class="token keyword">pub</span> puppet<span class="token punctuation">:</span> <span class="token class-name">Account</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Data</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> puppet_program<span class="token punctuation">:</span> <span class="token class-name">Program</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Puppet</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span></code></pre></div><p>Things to notice</p> <ul><li>We create a <code>CpiContext</code> object with the target instruction's accounts and program,
here <code>SetData</code> and <code>puppet_program</code>.</li> <li>To invoke an instruction on another program, just use the <code>cpi</code> module on the crate, here, <code>puppet::cpi::set_data</code>.</li> <li>Our <code>Accounts</code> struct contains the puppet account we are calling into via CPI. Accounts used for CPI are not specifically denoted
as such with the <code>CpiAccount</code> label since v0.15. Accounts used for CPI are not fundamentally different from <code>Program</code> or <code>Signer</code>
accounts except for their role and ownership in the specific context in which they are used.</li></ul> <div class="custom-block tip"><p class="custom-block-title">TIP</p> <p>When using another Anchor program for CPI, make sure to specify the <code>cpi</code> feature in your <code>Cargo.toml</code>.
If you look at the <code>Cargo.toml</code> for this example, you'll see
<code>puppet = { path = &quot;../puppet&quot;, features = [&quot;cpi&quot;] }</code>.</p></div> <h2 id="signer-seeds"><a href="#signer-seeds" class="header-anchor">#</a> Signer Seeds</h2> <p>Often it's useful for a program to sign instructions. For example, if a program controls a token
account and wants to send tokens to another account, it must sign. In Solana, this is done by specifying
&quot;signer seeds&quot; on CPI. To do this using the example above, simply change
<code>CpiContext::new(cpi_accounts, cpi_program)</code> to
<code>CpiContext::new_with_signer(cpi_accounts, cpi_program, signer_seeds)</code>.</p> <p>For more background on signing with program derived addresses, see the official Solana <a href="https://docs.solana.com/developing/programming-model/calling-between-programs#program-signed-accounts" target="_blank" rel="noopener noreferrer">documentation<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>.</p> <h2 id="return-values"><a href="#return-values" class="header-anchor">#</a> Return values</h2> <p>Solana currently has no way to return values from CPI, alas. However, you can approximate this
by having the callee write return values to an account and the caller read that account to
retrieve the return value. In future work, Anchor should do this transparently.</p> <h2 id="conclusion"><a href="#conclusion" class="header-anchor">#</a> Conclusion</h2> <p>Now that you can have your programs call other programs, you should be able to access all the work being done by other developers in your own applications!</p> <h2 id="next-steps"><a href="#next-steps" class="header-anchor">#</a> Next Steps</h2> <p>We just covered Cross Program Invocation and showed how anchor can handle talking to multiple different programs in the solana ecosystem. In the next step, we will teach you how to handle errors and in Anchor.</p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/anchor/tutorials/tutorial-2.html" class="prev">
Account Constraints and Access Control
</a></span> <span class="next"><a href="/anchor/tutorials/tutorial-4.html">
Errors
</a>
</span></p></div> </main></div><div class="global-ui"></div></div>
<script src="/anchor/assets/js/app.b2f13cd7.js" defer></script><script src="/anchor/assets/js/2.90291299.js" defer></script><script src="/anchor/assets/js/20.50564768.js" defer></script>
</body>
</html>