Skip to content

Commit

Permalink
Merge pull request #193 from metaplex-foundation/feature/allow-differ…
Browse files Browse the repository at this point in the history
…ent-accounts

Introduce Account, HotWallet, Create AccountMeta
  • Loading branch information
ajamaica authored Sep 23, 2022
2 parents 2412155 + 554955e commit 2e39f78
Show file tree
Hide file tree
Showing 24 changed files with 128 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ extension Action {
return
}
// create new account for token
guard let newAccount = Account(network: self.router.endpoint.network) else {
guard let newAccount = HotAccount(network: self.router.endpoint.network) else {
onComplete(.failure(SolanaError.unauthorized))
return
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/Solana/Actions/swap/swap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ extension Action {
var destination = destination

// add userTransferAuthority
guard let userTransferAuthority = Account(network: self.router.endpoint.network) else {
guard let userTransferAuthority = HotAccount(network: self.router.endpoint.network) else {
return .failure(SolanaError.other("Unsupported swapping tokens"))
}

Expand Down Expand Up @@ -217,7 +217,7 @@ extension Action {
signers: inout [Account],
minimumBalanceForRentExemption: UInt64
) -> Result<Account, Error> {
guard let newAccount = Account(network: self.router.endpoint.network) else {
guard let newAccount = HotAccount(network: self.router.endpoint.network) else {
return .failure(SolanaError.invalidRequest(reason: "Could not create new Account"))
}

Expand Down Expand Up @@ -258,7 +258,7 @@ extension Action {
signers: inout [Account],
minimumBalanceForRentExemption: UInt64
) -> Result<Account, Error> {
guard let newAccount = Account(network: self.router.endpoint.network) else {
guard let newAccount = HotAccount(network: self.router.endpoint.network) else {
return .failure(SolanaError.invalidRequest(reason: "Could not create new Account"))
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Solana/Extensions/AccountMeta+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

extension Array where Element == Account.Meta {
extension Array where Element == AccountMeta {
func index(ofElementWithPublicKey publicKey: PublicKey) -> Result<Int, Error> {
guard let index = firstIndex(where: {$0.publicKey == publicKey}) else {
return .failure( SolanaError.other("Could not found accountIndex"))}
Expand Down
64 changes: 36 additions & 28 deletions Sources/Solana/Models/Account.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import Foundation
import TweetNacl

public struct Account: Codable, Hashable {
public protocol Account {
var publicKey: PublicKey { get }
func sign(serializedMessage: Data) throws -> Data
}

public struct HotAccount: Codable, Hashable, Account {
public let phrase: [String]
public let publicKey: PublicKey
public let secretKey: Data


public func sign(serializedMessage: Data) throws -> Data {
let data = try NaclSign.signDetached(message: serializedMessage, secretKey: secretKey)
return data
}

public init?(phrase: [String] = [], network: Network, derivablePath: DerivablePath? = nil) {
let mnemonic: Mnemonic
var phrase = phrase.filter {!$0.isEmpty}
Expand Down Expand Up @@ -69,36 +79,34 @@ public struct Account: Codable, Hashable {
}
}

public extension Account {
struct Meta: Decodable, CustomDebugStringConvertible {
public let publicKey: PublicKey
public var isSigner: Bool
public var isWritable: Bool
public struct AccountMeta: Decodable, CustomDebugStringConvertible {
public let publicKey: PublicKey
public var isSigner: Bool
public var isWritable: Bool

// MARK: - Decodable
enum CodingKeys: String, CodingKey {
case pubkey, signer, writable
}
// MARK: - Decodable
enum CodingKeys: String, CodingKey {
case pubkey, signer, writable
}

public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
guard let newKey = PublicKey(string: try values.decode(String.self, forKey: .pubkey)) else {
throw SolanaError.invalidPublicKey
}
publicKey = newKey
isSigner = try values.decode(Bool.self, forKey: .signer)
isWritable = try values.decode(Bool.self, forKey: .writable)
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
guard let newKey = PublicKey(string: try values.decode(String.self, forKey: .pubkey)) else {
throw SolanaError.invalidPublicKey
}
publicKey = newKey
isSigner = try values.decode(Bool.self, forKey: .signer)
isWritable = try values.decode(Bool.self, forKey: .writable)
}

// Initializers
public init(publicKey: PublicKey, isSigner: Bool, isWritable: Bool) {
self.publicKey = publicKey
self.isSigner = isSigner
self.isWritable = isWritable
}
// Initializers
public init(publicKey: PublicKey, isSigner: Bool, isWritable: Bool) {
self.publicKey = publicKey
self.isSigner = isSigner
self.isWritable = isWritable
}

public var debugDescription: String {
"{\"publicKey\": \"\(publicKey.base58EncodedString)\", \"isSigner\": \(isSigner), \"isWritable\": \(isWritable)}"
}
public var debugDescription: String {
"{\"publicKey\": \"\(publicKey.base58EncodedString)\", \"isSigner\": \(isSigner), \"isWritable\": \(isWritable)}"
}
}
2 changes: 1 addition & 1 deletion Sources/Solana/Models/ConfirmedTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public struct ConfirmedTransactionFromBlock: Decodable {

public extension ConfirmedTransaction {
struct Message: Decodable {
public let accountKeys: [Account.Meta]
public let accountKeys: [AccountMeta]
public let instructions: [ParsedInstruction]
public let recentBlockhash: String
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Solana/Models/SendingTransaction/Message.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extension Transaction {
private static let RECENT_BLOCK_HASH_LENGTH = 32

// MARK: - Properties
var accountKeys: [Account.Meta]
var accountKeys: [AccountMeta]
var recentBlockhash: String
// var instructions: [Transaction.Instruction]
var programInstructions: [TransactionInstruction]
Expand Down
12 changes: 6 additions & 6 deletions Sources/Solana/Models/SendingTransaction/Transaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public struct Transaction {
.flatMap { signData in
for signer in signers {
do {
let data = try NaclSign.signDetached(message: signData, secretKey: signer.secretKey)
let data = try signer.sign(serializedMessage: signData)
try _addSignature(Signature(signature: data, publicKey: signer.publicKey)).get()
} catch let error {
return .failure(error)
Expand Down Expand Up @@ -148,7 +148,7 @@ public struct Transaction {

// programIds & accountMetas
var programIds = [PublicKey]()
var accountMetas = [Account.Meta]()
var accountMetas = [AccountMeta]()

for instruction in instructions {
accountMetas.append(contentsOf: instruction.keys)
Expand All @@ -171,7 +171,7 @@ public struct Transaction {
}

// filterOut duplicate account metas, keeps writable one
accountMetas = accountMetas.reduce([Account.Meta](), {result, accountMeta in
accountMetas = accountMetas.reduce([AccountMeta](), {result, accountMeta in
var uniqueMetas = result
if let index = uniqueMetas.firstIndex(where: {$0.publicKey == accountMeta.publicKey}) {
// if accountMeta exists
Expand All @@ -185,7 +185,7 @@ public struct Transaction {
// move fee payer to front
accountMetas.removeAll(where: {$0.publicKey == feePayer})
accountMetas.insert(
Account.Meta(publicKey: feePayer, isSigner: true, isWritable: true),
AccountMeta(publicKey: feePayer, isSigner: true, isWritable: true),
at: 0
)

Expand All @@ -205,8 +205,8 @@ public struct Transaction {
// header
var header = Message.Header()

var signedKeys = [Account.Meta]()
var unsignedKeys = [Account.Meta]()
var signedKeys = [AccountMeta]()
var unsignedKeys = [AccountMeta]()

for accountMeta in accountMetas {
// signed keys
Expand Down
6 changes: 3 additions & 3 deletions Sources/Solana/Models/TransactionInstruction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import Foundation
import Beet

public struct TransactionInstruction: Decodable {
public let keys: [Account.Meta]
public let keys: [AccountMeta]
public let programId: PublicKey
public let data: [UInt8]

init(keys: [Account.Meta], programId: PublicKey, data: [BytesEncodable]) {
init(keys: [AccountMeta], programId: PublicKey, data: [BytesEncodable]) {
self.keys = keys
self.programId = programId
self.data = data.bytes
}

public init(keys: [Account.Meta], programId: PublicKey, data: [UInt8]) {
public init(keys: [AccountMeta], programId: PublicKey, data: [UInt8]) {
self.keys = keys
self.programId = programId
self.data = data
Expand Down
10 changes: 5 additions & 5 deletions Sources/Solana/Programs/SystemProgram.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public struct SystemProgram {

TransactionInstruction(
keys: [
Account.Meta(publicKey: fromPublicKey, isSigner: true, isWritable: true),
Account.Meta(publicKey: newPubkey, isSigner: true, isWritable: true)
AccountMeta(publicKey: fromPublicKey, isSigner: true, isWritable: true),
AccountMeta(publicKey: newPubkey, isSigner: true, isWritable: true)
],
programId: PublicKey.systemProgramId,
data: [Index.create, lamports, space, programPubkey]
Expand All @@ -33,8 +33,8 @@ public struct SystemProgram {

TransactionInstruction(
keys: [
Account.Meta(publicKey: fromPublicKey, isSigner: true, isWritable: true),
Account.Meta(publicKey: toPublicKey, isSigner: false, isWritable: true)
AccountMeta(publicKey: fromPublicKey, isSigner: true, isWritable: true),
AccountMeta(publicKey: toPublicKey, isSigner: false, isWritable: true)
],
programId: PublicKey.programId,
data: [Index.transfer, lamports]
Expand All @@ -46,7 +46,7 @@ public struct SystemProgram {
) -> TransactionInstruction {
TransactionInstruction(
keys: [
Account.Meta(publicKey: destinationAccount, isSigner: false, isWritable: false)
AccountMeta(publicKey: destinationAccount, isSigner: false, isWritable: false)
],
programId: .ownerValidationProgramId,
data: [PublicKey.programId]
Expand Down
46 changes: 23 additions & 23 deletions Sources/Solana/Programs/TokenProgram.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public struct TokenProgram {

TransactionInstruction(
keys: [
Account.Meta(publicKey: mint, isSigner: false, isWritable: true),
Account.Meta(publicKey: PublicKey.sysvarRent, isSigner: false, isWritable: false)
AccountMeta(publicKey: mint, isSigner: false, isWritable: true),
AccountMeta(publicKey: PublicKey.sysvarRent, isSigner: false, isWritable: false)
],
programId: tokenProgramId,
data: [
Expand All @@ -49,10 +49,10 @@ public struct TokenProgram {

TransactionInstruction(
keys: [
Account.Meta(publicKey: account, isSigner: false, isWritable: true),
Account.Meta(publicKey: mint, isSigner: false, isWritable: false),
Account.Meta(publicKey: owner, isSigner: false, isWritable: false),
Account.Meta(publicKey: PublicKey.sysvarRent, isSigner: false, isWritable: false)
AccountMeta(publicKey: account, isSigner: false, isWritable: true),
AccountMeta(publicKey: mint, isSigner: false, isWritable: false),
AccountMeta(publicKey: owner, isSigner: false, isWritable: false),
AccountMeta(publicKey: PublicKey.sysvarRent, isSigner: false, isWritable: false)
],
programId: programId,
data: [Index.initializeAccount]
Expand All @@ -68,9 +68,9 @@ public struct TokenProgram {
) -> TransactionInstruction {
TransactionInstruction(
keys: [
Account.Meta(publicKey: source, isSigner: false, isWritable: true),
Account.Meta(publicKey: destination, isSigner: false, isWritable: true),
Account.Meta(publicKey: owner, isSigner: true, isWritable: true)
AccountMeta(publicKey: source, isSigner: false, isWritable: true),
AccountMeta(publicKey: destination, isSigner: false, isWritable: true),
AccountMeta(publicKey: owner, isSigner: true, isWritable: true)
],
programId: tokenProgramId,
data: [Index.transfer, amount]
Expand All @@ -86,22 +86,22 @@ public struct TokenProgram {
amount: UInt64
) -> TransactionInstruction {
var keys = [
Account.Meta(publicKey: account, isSigner: false, isWritable: true),
Account.Meta(publicKey: delegate, isSigner: false, isWritable: false)
AccountMeta(publicKey: account, isSigner: false, isWritable: true),
AccountMeta(publicKey: delegate, isSigner: false, isWritable: false)
]

if multiSigners.isEmpty {
keys.append(
Account.Meta(publicKey: owner, isSigner: true, isWritable: false)
AccountMeta(publicKey: owner, isSigner: true, isWritable: false)
)
} else {
keys.append(
Account.Meta(publicKey: owner, isSigner: false, isWritable: false)
AccountMeta(publicKey: owner, isSigner: false, isWritable: false)
)

for signer in multiSigners {
keys.append(
Account.Meta(publicKey: signer.publicKey, isSigner: true, isWritable: false)
AccountMeta(publicKey: signer.publicKey, isSigner: true, isWritable: false)
)
}
}
Expand All @@ -123,9 +123,9 @@ public struct TokenProgram {

TransactionInstruction(
keys: [
Account.Meta(publicKey: mint, isSigner: false, isWritable: true),
Account.Meta(publicKey: destination, isSigner: false, isWritable: true),
Account.Meta(publicKey: authority, isSigner: true, isWritable: false)
AccountMeta(publicKey: mint, isSigner: false, isWritable: true),
AccountMeta(publicKey: destination, isSigner: false, isWritable: true),
AccountMeta(publicKey: authority, isSigner: true, isWritable: false)
],
programId: tokenProgramId,
data: [Index.mintTo, amount]
Expand All @@ -141,9 +141,9 @@ public struct TokenProgram {

TransactionInstruction(
keys: [
Account.Meta(publicKey: account, isSigner: false, isWritable: true),
Account.Meta(publicKey: destination, isSigner: false, isWritable: true),
Account.Meta(publicKey: owner, isSigner: false, isWritable: false)
AccountMeta(publicKey: account, isSigner: false, isWritable: true),
AccountMeta(publicKey: destination, isSigner: false, isWritable: true),
AccountMeta(publicKey: owner, isSigner: false, isWritable: false)
],
programId: tokenProgramId,
data: [Index.closeAccount]
Expand All @@ -161,9 +161,9 @@ public struct TokenProgram {
decimals: Decimals
) -> TransactionInstruction {
var keys = [
Account.Meta(publicKey: source, isSigner: false, isWritable: true),
Account.Meta(publicKey: mint, isSigner: false, isWritable: false),
Account.Meta(publicKey: destination, isSigner: false, isWritable: true)
AccountMeta(publicKey: source, isSigner: false, isWritable: true),
AccountMeta(publicKey: mint, isSigner: false, isWritable: false),
AccountMeta(publicKey: destination, isSigner: false, isWritable: true)
]

if multiSigners.count == 0 {
Expand Down
Loading

0 comments on commit 2e39f78

Please sign in to comment.