Solana DEV #01: 올바른 방식으로 온체인 데이터 가져오기

클라이언트 측에서 솔라나 탈중앙화 앱으로 작업하는 것은 솔라나 앱 개발의 핵심 부분이 될 수 있습니다. 프로세스에 익숙해지기 전에 스마트 계약 프로그래밍이 우리가 철저히 신경써야 할 유일한 관심사라고 생각했습니다. 그러나 기존 웹 사이트 개발과 마찬가지로 클라이언트 측에서 데이터 가져오기는 사용자에게 제공되는 경험에 영향을 미칩니다. 이 기사에서는 데이터 가져오기의 주요 사항을 나열합니다.

필터링된 프로그램 계정 가져오기



가장 중요한 모범 사례는 필터와 함께 getProgramAccounts를 사용하는 것입니다. getProgramAccounts 패키지의 이 @solana/web3.js 메서드는 제공된 프로그램 ID의 모든 계정을 가져오는 데 매우 유용합니다. 그러나 스마트 계약에서와 같이 여러 유형의 계정이 있으므로 최상의 성능을 위해 필터링이 필요합니다.

/**
 * A filter object for getProgramAccounts
 */
export type GetProgramAccountsFilter = MemcmpFilter | DataSizeFilter;


이제 우리는 소스 코드를 약간 가지고 놀았습니다. MemcmpFilterDataSizeFilter를 참조할 수 있는 두 가지 필터링 유형이 있습니다.

데이터 크기 필터




/**
 * Data size comparison filter for getProgramAccounts
 */
export type DataSizeFilter = {
  /** Size of data for program account data length comparison */
  dataSize: number;
};

DataSizeFilter는 선언된 데이터 크기와 일치하는 프로그램의 계정을 필터링하는 데 사용됩니다. 간단하죠? 이 필터링 유형은 데이터 크기가 고정된 계정에 유용합니다. 계정에는 vector 또는 str 와 같은 동적 크기 필드가 포함됩니다.

Memcmp 필터




/**
 * Memory comparison filter for getProgramAccounts
 */
export type MemcmpFilter = {
  memcmp: {
    /** offset into program account data to start comparison */
    offset: number;
    /** data to match, as base-58 encoded string and limited to less than 129 bytes */
    bytes: string;
  };
};


두 가지 필터링 유형 중에서 이 접근 방식을 사용하면 보다 동적이고 선택적인 방식으로 계정을 필터링할 수 있으므로 더 많이 사용됩니다. MemcmpFilter 또는 Memory comparison filter에는 offsetbytes라는 두 개의 필드가 있습니다. 모든 계정 데이터는 바이트 집합이며 오프셋을 사용하여 비교할 특정 데이터 필드를 선택할 수 있으며 바이트는 비교의 후반 부분입니다.

예를 들어 특정 계정 구분자가 있는 모든 프로그램 계정을 가져오려는 경우 오프셋을 0으로 설정하고 비교된 계정 구분자의 바이트를 가져올 수 있습니다. 이것은 Anchor를 사용하지 않고 특정 유형의 프로그램 계정을 얻는 트릭입니다(프레임워크가 이미 내부에서 이 프로세스를 처리하므로).

저는 보통 이 필터링 유형을 사용하여 특정 지갑이 소유한 계정을 필터링합니다. 이를 위해서는 Rust 프로그램에서 소유자의 지갑 주소를 계정에 저장해야 합니다. 예를 들어 다음 계정 데이터가 있습니다(Anchor 사용).

#[account]
pub struct WalletAddressContainer {
  pub address: PubKey
}


특정 지갑 주소의 모든 WalletAddressContainer 계정을 가져오려면

// using Anchor
await program.account.flow.all([
 {
  memcmp: {
    offset: 8,
    bytes: publicKey.toBase58(),
  },
 }
]);

// without Anchor
await connection.getProgramAccounts(
 programID,
 {
  ...,
  filters: [
   {
    memcmp: {
     offset: 0,
     bytes: /** Account discriminator bytes of WalletAddressContainer **/,
    }
   },
   {
    memcmp: {
     offset: 8,
     bytes: publicKey.toBase58()
    }
   }
  ]
 }
);


언급한 바와 같이 Anchor 방식으로 Anchor 프레임워크는 내부적으로 계정 판별자를 비교하므로 다시 비교할 필요가 없습니다. 그런 식으로 우리는 지갑의 공개 키를 비교하기 위해 하나의 필터memcmp만 필요하지만 오프셋은 여전히 ​​8이어야 합니다.

반면 Anchor가 없는 getProgramAccounts는 두 가지 비교가 필요합니다. 첫 번째는 계정 구분자이고 두 번째는 지갑 주소입니다.

좋은 웹페이지 즐겨찾기